<commit_before>// Copyright 2018, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::borrow::Borrow;
use std::cmp::Ordering;
use std::ffi::{CStr, CString, OsStr};
use std::fmt;
use std::ops::Deref;
use std::os::raw::c_char;
use std::ptr;
use std::slice;
use std::string::String;
use translate::*;
use types::{StaticType, Type};
use libc;

use gobject_ffi;
use ffi as glib_ffi;
use value::{FromValueOptional, Value, SetValueOptional, SetValue};

#[derive(Debug)]
pub enum GString {
    ForeignOwned(CString),
    Borrowed(*const c_char, usize),
    Owned(*mut c_char, usize)
}

impl GString {
    pub unsafe fn new(ptr: *mut c_char) -> Self {
        assert!(!ptr.is_null());
        GString::Owned(ptr, libc::strlen(ptr))
    }

    pub unsafe fn new_borrowed(ptr: *const c_char) -> Self {
        assert!(!ptr.is_null());
        GString::Borrowed(ptr, libc::strlen(ptr))
    }

    pub fn as_str(&self) -> &str {
        let cstr = match self {
            GString::Borrowed(ptr, length) => unsafe {
                let bytes = slice::from_raw_parts(*ptr as *const u8, length + 1);
                CStr::from_bytes_with_nul_unchecked(bytes)
            }
            GString::Owned(ptr, length) => unsafe {
                let bytes = slice::from_raw_parts(*ptr as *const u8, length + 1);
                CStr::from_bytes_with_nul_unchecked(bytes)
            }
            GString::ForeignOwned(cstring) => {
                cstring.as_c_str()
            }
        };
        cstr.to_str().unwrap()
    }
}

impl Drop for GString {
    fn drop(&mut self) {
        if let GString::Owned(ptr, _len) = self {
            unsafe {
                glib_ffi::g_free(*ptr as *mut _);
            }
        }
    }
}

impl fmt::Display for GString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

impl Borrow<str> for GString {
    fn borrow(&self) -> &str {
        self.as_str()
    }
}

impl Ord for GString {
    fn cmp(&self, other: &GString) -> Ordering {
        self.as_str().cmp(other.as_str())
    }
}

impl PartialOrd for GString {
    fn partial_cmp(&self, other: &GString) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for GString {
    fn eq(&self, other: &GString) -> bool {
        self.as_str() == other.as_str()
    }
}

impl PartialEq<GString> for String {
    fn eq(&self, other: &GString) -> bool {
        self.as_str() == other.as_str()
    }
}

impl PartialEq<str> for GString {
    fn eq(&self, other: &str) -> bool {
        self.as_str() == other
    }
}

impl<'a> PartialEq<&'a str> for GString {
    fn eq(&self, other: &&'a str) -> bool {
        self.as_str() == *other
    }
}

impl<'a> PartialEq<GString> for &'a str {
    fn eq(&self, other: &GString) -> bool {
        *self == other.as_str()
    }
}

impl PartialEq<String> for GString {
    fn eq(&self, other: &String) -> bool {
        self.as_str() == other.as_str()
    }
}

impl PartialEq<GString> for str {
    fn eq(&self, other: &GString) -> bool {
        self == other.as_str()
    }
}

impl PartialOrd<GString> for String {
    fn partial_cmp(&self, other: &GString) -> Option<Ordering> {
        Some(self.cmp(&String::from(other.as_str())))
    }
}

impl PartialOrd<String> for GString {
    fn partial_cmp(&self, other: &String) -> Option<Ordering> {
        Some(self.as_str().cmp(other.as_str()))
    }
}

impl PartialOrd<GString> for str {
    fn partial_cmp(&self, other: &GString) -> Option<Ordering> {
        Some(self.cmp(&other))
    }
}

impl PartialOrd<str> for GString {
    fn partial_cmp(&self, other: &str) -> Option<Ordering> {
        Some(self.as_str().cmp(other))
    }
}

impl Eq for GString {}

impl AsRef<str> for GString {
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

impl AsRef<OsStr> for GString {
    fn as_ref(&self) -> &OsStr {
        OsStr::new(self.as_str())
    }
}

impl Deref for GString {
    type Target = str;

    fn deref(&self) -> &str {
        self.as_str()
    }
}

impl From<GString> for String {
    #[inline]
    fn from(s: GString) -> Self {
        String::from(s.as_str())
    }
}

impl From<GString> for Box<str> {
    #[inline]
    fn from(s: GString) -> Self {
        let st: String = s.into();
        st.into_boxed_str()
    }
}

impl From<String> for GString {
    #[inline]
    fn from(s: String) -> Self {
        s.as_bytes().to_vec().into()
    }
}

impl From<Box<str>> for GString {
    #[inline]
    fn from(s: Box<str>) -> Self {
        s.as_bytes().to_vec().into()
    }
}

impl<'a> From<&'a str> for GString {
    #[inline]
    fn from(s: &'a str) -> Self {
        s.as_bytes().to_vec().into()
    }
}

impl From<Vec<u8>> for GString {
    #[inline]
    fn from(s: Vec<u8>) -> Self {
        let cstring = CString::new(s).expect("CString::new failed");
        cstring.into()
    }
}

impl From<CString> for GString {
    #[inline]
    fn from(s: CString) -> Self {
        GString::ForeignOwned(s)
    }
}

impl<'a> From<&'a CStr> for GString {
    #[inline]
    fn from(c: &'a CStr) -> Self {
        CString::from(c).into()
    }
}

impl FromGlibPtrFull<*const c_char> for GString {
    #[inline]
    unsafe fn from_glib_full(ptr: *const c_char) -> Self {
        GString::new(ptr as *mut _)
    }
}

impl FromGlibPtrFull<*mut u8> for GString {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut u8) -> Self {
        GString::new(ptr as *mut _)
    }
}

impl FromGlibPtrFull<*mut i8> for GString {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut i8) -> Self {
        GString::new(ptr as *mut _)
    }
}

impl FromGlibPtrNone<*const c_char> for GString {
    #[inline]
    unsafe fn from_glib_none(ptr: *const c_char) -> Self {
        let cstr = CStr::from_ptr(ptr);
        cstr.into()
    }
}

impl FromGlibPtrNone<*mut u8> for GString {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut u8) -> Self {
        let cstr = CStr::from_ptr(ptr as *mut _);
        cstr.into()
    }
}

impl FromGlibPtrNone<*mut i8> for GString {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut i8) -> Self {
        let cstr = CStr::from_ptr(ptr as *mut _);
        cstr.into()
    }
}

impl FromGlibPtrBorrow<*const c_char> for GString {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *const c_char) -> Self {
        GString::new_borrowed(ptr)
    }
}

impl FromGlibPtrBorrow<*mut u8> for GString {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut u8) -> Self {
        GString::new_borrowed(ptr as *const c_char)
    }
}

impl FromGlibPtrBorrow<*mut i8> for GString {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut i8) -> Self {
        GString::new_borrowed(ptr as *const c_char)
    }
}

impl<'a> ToGlibPtr<'a, *const c_char> for GString {
    type Storage = &'a Self;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
        Stash(self.as_ptr() as *const _, self)
    }

    #[inline]
    fn to_glib_full(&self) -> *const c_char {
        unsafe {
            glib_ffi::g_strndup(self.as_ptr() as *const c_char, self.len() as libc::size_t)
                as *const c_char
        }
    }
}

impl<'a> ToGlibPtr<'a, *mut c_char> for GString {
    type Storage = &'a Self;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
        Stash(self.as_ptr() as *mut _, self)
    }

    #[inline]
    fn to_glib_full(&self) -> *mut c_char {
        unsafe {
            glib_ffi::g_strndup(self.as_ptr() as *const c_char, self.len() as libc::size_t)
                as *mut c_char
        }
    }
}

impl GlibPtrDefault for GString {
    type GlibType = *const c_char;
}

impl StaticType for GString {
    fn static_type() -> Type {
        String::static_type()
    }
}

impl StaticType for Vec<GString> {
    fn static_type() -> Type {
        unsafe {
            from_glib(glib_ffi::g_strv_get_type())
        }
    }
}

impl<'a> FromValueOptional<'a> for GString {
    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
        let val = value.to_glib_none().0;
        if val.is_null() {
            None
        } else {
            let ptr = gobject_ffi::g_value_dup_string(val);
            Some(GString::new(ptr))
        }
    }
}

impl SetValue for GString {
    unsafe fn set_value(value: &mut Value, this: &Self) {
        gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl SetValueOptional for GString {
    unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
        gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl_from_glib_container_as_vec_string!(GString, *const c_char);
impl_from_glib_container_as_vec_string!(GString, *mut c_char);

#[cfg(test)]
mod tests {
    use gstring::GString;
    use std::ffi::CString;
    use ffi as glib_ffi;

    #[test]
    fn test_gstring() {
        let data = CString::new("foo").unwrap();
        let ptr = data.into_raw();

        unsafe {
            let ptr_copy = glib_ffi::g_strdup(ptr);
            let gstring = GString::new(ptr_copy);
            assert_eq!(gstring.as_str(), "foo");
            let foo: Box<str> = gstring.into();
            assert_eq!(foo.as_ref(), "foo");
        }
    }

    #[test]
    fn test_owned_glib_string() {
        let data = CString::new("foo").unwrap();
        let ptr = data.into_raw();
        unsafe {
            let ptr_copy = glib_ffi::g_strdup(ptr);
            let gstr = GString::new(ptr_copy);
            assert_eq!(gstr, "foo");
        }
    }

    #[test]
    fn test_gstring_from_str() {
        let gstring: GString = "foo".into();
        assert_eq!(gstring.as_str(), "foo");
        let foo: Box<str> = gstring.into();
        assert_eq!(foo.as_ref(), "foo");
    }

    #[test]
    fn test_gstring_from_cstring() {
        let cstr = CString::new("foo").unwrap();
        let gstring = GString::from(cstr);
        assert_eq!(gstring.as_str(), "foo");
        let foo: Box<str> = gstring.into();
        assert_eq!(foo.as_ref(), "foo");
    }

    #[test]
    fn test_string_from_gstring() {
        let cstr = CString::new("foo").unwrap();
        let gstring = GString::from(cstr);
        assert_eq!(gstring.as_str(), "foo");
        let s = String::from(gstring);
        assert_eq!(s, "foo");
    }

    #[test]
    fn test_vec_u8_to_gstring() {
        let v = "foo".as_bytes();
        let s: GString = Vec::from(v).into();
        assert_eq!(s.as_str(), "foo");
    }

}
<commit_msg>GString: Avoid copies when converting from/to String<commit_after>// Copyright 2018, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::borrow::Borrow;
use std::cmp::Ordering;
use std::ffi::{CStr, CString, OsStr};
use std::fmt;
use std::ops::Deref;
use std::os::raw::c_char;
use std::ptr;
use std::slice;
use std::string::String;
use translate::*;
use types::{StaticType, Type};
use libc;

use gobject_ffi;
use ffi as glib_ffi;
use value::{FromValueOptional, Value, SetValueOptional, SetValue};

#[derive(Debug)]
pub enum GString {
    ForeignOwned(Option<CString>),
    Borrowed(*const c_char, usize),
    Owned(*mut c_char, usize)
}

impl GString {
    pub unsafe fn new(ptr: *mut c_char) -> Self {
        assert!(!ptr.is_null());
        GString::Owned(ptr, libc::strlen(ptr))
    }

    pub unsafe fn new_borrowed(ptr: *const c_char) -> Self {
        assert!(!ptr.is_null());
        GString::Borrowed(ptr, libc::strlen(ptr))
    }

    pub fn as_str(&self) -> &str {
        let cstr = match self {
            GString::Borrowed(ptr, length) => unsafe {
                let bytes = slice::from_raw_parts(*ptr as *const u8, length + 1);
                CStr::from_bytes_with_nul_unchecked(bytes)
            }
            GString::Owned(ptr, length) => unsafe {
                let bytes = slice::from_raw_parts(*ptr as *const u8, length + 1);
                CStr::from_bytes_with_nul_unchecked(bytes)
            }
            GString::ForeignOwned(cstring) => {
                cstring.as_ref().expect("ForeignOwned shouldn't be empty").as_c_str()
            }
        };
        cstr.to_str().unwrap()
    }
}

impl Drop for GString {
    fn drop(&mut self) {
        if let GString::Owned(ptr, _len) = self {
            unsafe {
                glib_ffi::g_free(*ptr as *mut _);
            }
        }
    }
}

impl fmt::Display for GString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

impl Borrow<str> for GString {
    fn borrow(&self) -> &str {
        self.as_str()
    }
}

impl Ord for GString {
    fn cmp(&self, other: &GString) -> Ordering {
        self.as_str().cmp(other.as_str())
    }
}

impl PartialOrd for GString {
    fn partial_cmp(&self, other: &GString) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for GString {
    fn eq(&self, other: &GString) -> bool {
        self.as_str() == other.as_str()
    }
}

impl PartialEq<GString> for String {
    fn eq(&self, other: &GString) -> bool {
        self.as_str() == other.as_str()
    }
}

impl PartialEq<str> for GString {
    fn eq(&self, other: &str) -> bool {
        self.as_str() == other
    }
}

impl<'a> PartialEq<&'a str> for GString {
    fn eq(&self, other: &&'a str) -> bool {
        self.as_str() == *other
    }
}

impl<'a> PartialEq<GString> for &'a str {
    fn eq(&self, other: &GString) -> bool {
        *self == other.as_str()
    }
}

impl PartialEq<String> for GString {
    fn eq(&self, other: &String) -> bool {
        self.as_str() == other.as_str()
    }
}

impl PartialEq<GString> for str {
    fn eq(&self, other: &GString) -> bool {
        self == other.as_str()
    }
}

impl PartialOrd<GString> for String {
    fn partial_cmp(&self, other: &GString) -> Option<Ordering> {
        Some(self.cmp(&String::from(other.as_str())))
    }
}

impl PartialOrd<String> for GString {
    fn partial_cmp(&self, other: &String) -> Option<Ordering> {
        Some(self.as_str().cmp(other.as_str()))
    }
}

impl PartialOrd<GString> for str {
    fn partial_cmp(&self, other: &GString) -> Option<Ordering> {
        Some(self.cmp(&other))
    }
}

impl PartialOrd<str> for GString {
    fn partial_cmp(&self, other: &str) -> Option<Ordering> {
        Some(self.as_str().cmp(other))
    }
}

impl Eq for GString {}

impl AsRef<str> for GString {
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

impl AsRef<OsStr> for GString {
    fn as_ref(&self) -> &OsStr {
        OsStr::new(self.as_str())
    }
}

impl Deref for GString {
    type Target = str;

    fn deref(&self) -> &str {
        self.as_str()
    }
}

impl From<GString> for String {
    #[inline]
    fn from(mut s: GString) -> Self {
        if let GString::ForeignOwned(ref mut cstring) = s {
            if let Ok(s) = cstring.take().expect("ForeignOwned shouldn't be empty").into_string() {
                return s;
            }
        }
        String::from(s.as_str())
    }
}

impl From<GString> for Box<str> {
    #[inline]
    fn from(s: GString) -> Self {
        let st: String = s.into();
        st.into_boxed_str()
    }
}

impl From<String> for GString {
    #[inline]
    fn from(s: String) -> Self {
        s.into_bytes().into()
    }
}

impl From<Box<str>> for GString {
    #[inline]
    fn from(s: Box<str>) -> Self {
        s.as_bytes().to_vec().into()
    }
}

impl<'a> From<&'a str> for GString {
    #[inline]
    fn from(s: &'a str) -> Self {
        s.as_bytes().to_vec().into()
    }
}

impl From<Vec<u8>> for GString {
    #[inline]
    fn from(s: Vec<u8>) -> Self {
        let cstring = CString::new(s).expect("CString::new failed");
        cstring.into()
    }
}

impl From<CString> for GString {
    #[inline]
    fn from(s: CString) -> Self {
        GString::ForeignOwned(Some(s))
    }
}

impl<'a> From<&'a CStr> for GString {
    #[inline]
    fn from(c: &'a CStr) -> Self {
        CString::from(c).into()
    }
}

impl FromGlibPtrFull<*const c_char> for GString {
    #[inline]
    unsafe fn from_glib_full(ptr: *const c_char) -> Self {
        GString::new(ptr as *mut _)
    }
}

impl FromGlibPtrFull<*mut u8> for GString {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut u8) -> Self {
        GString::new(ptr as *mut _)
    }
}

impl FromGlibPtrFull<*mut i8> for GString {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut i8) -> Self {
        GString::new(ptr as *mut _)
    }
}

impl FromGlibPtrNone<*const c_char> for GString {
    #[inline]
    unsafe fn from_glib_none(ptr: *const c_char) -> Self {
        let cstr = CStr::from_ptr(ptr);
        cstr.into()
    }
}

impl FromGlibPtrNone<*mut u8> for GString {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut u8) -> Self {
        let cstr = CStr::from_ptr(ptr as *mut _);
        cstr.into()
    }
}

impl FromGlibPtrNone<*mut i8> for GString {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut i8) -> Self {
        let cstr = CStr::from_ptr(ptr as *mut _);
        cstr.into()
    }
}

impl FromGlibPtrBorrow<*const c_char> for GString {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *const c_char) -> Self {
        GString::new_borrowed(ptr)
    }
}

impl FromGlibPtrBorrow<*mut u8> for GString {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut u8) -> Self {
        GString::new_borrowed(ptr as *const c_char)
    }
}

impl FromGlibPtrBorrow<*mut i8> for GString {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut i8) -> Self {
        GString::new_borrowed(ptr as *const c_char)
    }
}

impl<'a> ToGlibPtr<'a, *const c_char> for GString {
    type Storage = &'a Self;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
        Stash(self.as_ptr() as *const _, self)
    }

    #[inline]
    fn to_glib_full(&self) -> *const c_char {
        unsafe {
            glib_ffi::g_strndup(self.as_ptr() as *const c_char, self.len() as libc::size_t)
                as *const c_char
        }
    }
}

impl<'a> ToGlibPtr<'a, *mut c_char> for GString {
    type Storage = &'a Self;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
        Stash(self.as_ptr() as *mut _, self)
    }

    #[inline]
    fn to_glib_full(&self) -> *mut c_char {
        unsafe {
            glib_ffi::g_strndup(self.as_ptr() as *const c_char, self.len() as libc::size_t)
                as *mut c_char
        }
    }
}

impl GlibPtrDefault for GString {
    type GlibType = *const c_char;
}

impl StaticType for GString {
    fn static_type() -> Type {
        String::static_type()
    }
}

impl StaticType for Vec<GString> {
    fn static_type() -> Type {
        unsafe {
            from_glib(glib_ffi::g_strv_get_type())
        }
    }
}

impl<'a> FromValueOptional<'a> for GString {
    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
        let val = value.to_glib_none().0;
        if val.is_null() {
            None
        } else {
            let ptr = gobject_ffi::g_value_dup_string(val);
            Some(GString::new(ptr))
        }
    }
}

impl SetValue for GString {
    unsafe fn set_value(value: &mut Value, this: &Self) {
        gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl SetValueOptional for GString {
    unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
        gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl_from_glib_container_as_vec_string!(GString, *const c_char);
impl_from_glib_container_as_vec_string!(GString, *mut c_char);

#[cfg(test)]
mod tests {
    use gstring::GString;
    use std::ffi::CString;
    use ffi as glib_ffi;

    #[test]
    fn test_gstring() {
        let data = CString::new("foo").unwrap();
        let ptr = data.into_raw();

        unsafe {
            let ptr_copy = glib_ffi::g_strdup(ptr);
            let gstring = GString::new(ptr_copy);
            assert_eq!(gstring.as_str(), "foo");
            let foo: Box<str> = gstring.into();
            assert_eq!(foo.as_ref(), "foo");
        }
    }

    #[test]
    fn test_owned_glib_string() {
        let data = CString::new("foo").unwrap();
        let ptr = data.into_raw();
        unsafe {
            let ptr_copy = glib_ffi::g_strdup(ptr);
            let gstr = GString::new(ptr_copy);
            assert_eq!(gstr, "foo");
        }
    }

    #[test]
    fn test_gstring_from_str() {
        let gstring: GString = "foo".into();
        assert_eq!(gstring.as_str(), "foo");
        let foo: Box<str> = gstring.into();
        assert_eq!(foo.as_ref(), "foo");
    }

    #[test]
    fn test_gstring_from_cstring() {
        let cstr = CString::new("foo").unwrap();
        let gstring = GString::from(cstr);
        assert_eq!(gstring.as_str(), "foo");
        let foo: Box<str> = gstring.into();
        assert_eq!(foo.as_ref(), "foo");
    }

    #[test]
    fn test_string_from_gstring() {
        let cstr = CString::new("foo").unwrap();
        let gstring = GString::from(cstr);
        assert_eq!(gstring.as_str(), "foo");
        let s = String::from(gstring);
        assert_eq!(s, "foo");
    }

    #[test]
    fn test_vec_u8_to_gstring() {
        let v = "foo".as_bytes();
        let s: GString = Vec::from(v).into();
        assert_eq!(s.as_str(), "foo");
    }

}
<|endoftext|>


<commit_before>use luminance::{Dim2, Equation, Factor, Flat, Framebuffer, Mode, Pipe, Pipeline, RenderCommand, ShadingCommand, Tess, TessRender, TessVertices, Uniform, Unit, Vertex, VertexFormat};

use resource::Res;
use scene::Scene;
use shader::Program;
use text::TextTexture;
use texture::{RGBA32F, Texture};

/// Vertex used in overlay’s objects.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vert {
  /// Position.
  pub pos: [f32; 3],
  /// Color.
  pub color: [f32; 4]
}

impl Vert {
  pub fn new(pos: [f32; 3], color: [f32; 4]) -> Self {
    Vert {
      pos: pos,
      color: color
    }
  }
}

impl Vertex for Vert {
  fn vertex_format() -> VertexFormat {
    <([f32; 3], [f32; 4]) as Vertex>::vertex_format()
  }
}

pub struct Triangle(pub Vert, pub Vert, pub Vert);

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Disc {
  center: Vert,
  radius: f32
}

impl Disc {
  pub fn new(center: Vert, radius: f32) -> Self {
    Disc {
      center: center,
      radius: radius
    }
  }
}

impl Vertex for Disc {
  fn vertex_format() -> VertexFormat {
    <(Vert, f32) as Vertex>::vertex_format()
  }
}

pub type Texture2D = Texture<Flat, Dim2, RGBA32F>;

pub struct Text<'a> {
  text_texture: &'a TextTexture,
  left_upper: Vert
}

impl<'a> Text<'a> {
  pub fn new(text_texture: &'a TextTexture, left_upper: Vert) -> Self {
    Text {
      text_texture: text_texture,
      left_upper: left_upper
    }
  }
}

const DISC_SCREEN_RATIO: &'static Uniform<f32> = &Uniform::new(0);

const TEXT_SAMPLER: &'static Uniform<Unit> = &Uniform::new(0);
const TEXT_POS: &'static Uniform<[f32; 3]> = &Uniform::new(1);
const TEXT_SIZE: &'static Uniform<[f32; 2]> = &Uniform::new(2);
const TEXT_SCALE: &'static Uniform<f32> = &Uniform::new(3);
const TEXT_COLOR: &'static Uniform<[f32; 4]> = &Uniform::new(4);

/// A renderer responsible of rendering shapes.
pub struct Renderer {
  framebuffer: Framebuffer<Flat, Dim2, Texture2D, ()>,
  ratio: f32,
  tri_program: Res<Program>,
  tris: Tess,
  tri_vert_nb: usize,
  disc_program: Res<Program>,
  discs: Tess,
  disc_vert_nb: usize,
  text_program: Res<Program>,
  text_quad: Tess,
  overlay_unit: OverlayUnit,
}

impl Renderer {
  pub fn new(w: u32, h: u32, max_tris: usize, max_discs: usize, scene: &mut Scene) -> Self {
    let fb = Framebuffer::new((w, h), 0).unwrap();

    let tri_program = scene.get("spectra/overlay/triangle.glsl", vec![]).unwrap();
    let tris = Tess::new(Mode::Triangle, TessVertices::Reserve::<Vert>(max_tris * 3), None);

    let disc_program = scene.get("spectra/overlay/disc.glsl", vec![DISC_SCREEN_RATIO.sem("ratio")]).unwrap();
    let discs = Tess::new(Mode::Point, TessVertices::Reserve::<Disc>(max_discs), None);

    let text_program = scene.get("spectra/overlay/text.glsl", vec![
      TEXT_SAMPLER.sem("text_texture"),
      TEXT_POS.sem("pos"),
      TEXT_SIZE.sem("size"),
      TEXT_SCALE.sem("scale"),
      TEXT_COLOR.sem("color")
    ]).unwrap();

    let text_quad = Tess::attributeless(Mode::TriangleStrip, 4);

    Renderer {
      framebuffer: fb,
      ratio: w as f32 / h as f32,
      tri_program: tri_program,
      tris: tris,
      tri_vert_nb: 0,
      disc_program: disc_program,
      discs: discs,
      disc_vert_nb: 0,
      text_program: text_program,
      text_quad: text_quad,
      overlay_unit: OverlayUnit::new(w, h)
    }
  }

  fn dispatch(&mut self, input: &RenderInput) {
    let mut tris = self.tris.as_slice_mut().unwrap();
    let mut tri_i = 0;
    let mut discs = self.discs.as_slice_mut().unwrap();
    let mut disc_i = 0;

    for &Triangle(a, b, c) in input.triangles {
      tris[tri_i] = a;
      tri_i += 1;

      tris[tri_i] = b;
      tri_i += 1;

      tris[tri_i] = c;
      tri_i += 1;
    }

    for disc in input.discs {
      discs[disc_i] = *disc;
      disc_i += 1;
    }

    self.tri_vert_nb = tri_i;
    self.disc_vert_nb = disc_i;
  }

  pub fn render(&mut self, input: RenderInput) -> &Texture2D {
    self.dispatch(&input);

    let tris = TessRender::one_sub(&self.tris, self.tri_vert_nb);
    let discs = TessRender::one_sub(&self.discs, self.disc_vert_nb);
    let text_quad = TessRender::one_whole(&self.text_quad);

    // FIXME: no alloc?
    let text_uniforms: Vec<_> = input.texts.map(|(texts, text_scale)| texts.iter().map(|text| {
      let (tex_w, tex_h) = text.text_texture.size();

      [
        TEXT_SAMPLER.alter(Unit::new(0)),
        TEXT_POS.alter(text.left_upper.pos),
        TEXT_SIZE.alter(self.overlay_unit.from_window(tex_w, tex_h)),
        TEXT_SCALE.alter(text_scale),
        TEXT_COLOR.alter(text.left_upper.color),
      ]
    }).collect()).unwrap_or(Vec::new());

    let text_textures: Vec<_> = input.texts.map(|(texts, _)| texts.iter().map(|text| [&***text.text_texture]).collect()).unwrap_or(Vec::new());

    let text_render_cmds: Vec<_> = input.texts.iter().enumerate().map(|(i, _)| {
        let blending = (Equation::Additive, Factor::One, Factor::SrcAlphaComplement);
        Pipe::empty()
          .uniforms(&text_uniforms[i])
          .textures(&text_textures[i])
          .unwrap(RenderCommand::new(Some(blending), true, vec![
            Pipe::new(text_quad.clone())
          ]))
      }).collect();

    let disc_uniforms = [
      DISC_SCREEN_RATIO.alter(self.ratio)
    ];

    Pipeline::new(&self.framebuffer, [0., 0., 0., 0.], &[], &[], vec![
      // render triangles
      Pipe::new(ShadingCommand::new(&self.tri_program.borrow(), vec![
        Pipe::new(RenderCommand::new(None, true, vec![
          Pipe::new(tris)
        ]))
      ])),
      // render discs
      Pipe::empty()
        .uniforms(&disc_uniforms)
        .unwrap(ShadingCommand::new(&self.disc_program.borrow(), vec![
          Pipe::new(RenderCommand::new(None, true, vec![
            Pipe::new(discs)
          ]))
        ])),
      // render texts
      Pipe::new(ShadingCommand::new(&self.text_program.borrow(), text_render_cmds))
    ]).run();

    &self.framebuffer.color_slot
  }
}

pub struct RenderInput<'a, 'b> where 'b: 'a {
  triangles: &'a [Triangle],
  discs: &'a [Disc],
  texts: Option<(&'a [Text<'b>], f32)>
}

impl<'a, 'b> RenderInput<'a, 'b> {
  pub fn new() -> Self {
    RenderInput {
      triangles: &[],
      discs: &[],
      texts: None,
    }
  }

  pub fn triangles(self, triangles: &'a [Triangle]) -> Self {
    RenderInput {
      triangles: triangles, ..self
    }
  }

  pub fn discs(self, discs: &'a [Disc]) -> Self {
    RenderInput {
      discs: discs,
      ..self
    }
  }

  pub fn texts(self, texts: &'a [Text<'b>], scale: f32) -> Self {
    RenderInput {
      texts: Some((texts, scale.max(0.))),
      ..self
    }
  }
}

/// Overlay units are used to position stuff in overlay in a universal way and screen independent
/// way. The screen uses normalized coordinates with the origin at lower left as the following
/// diagram:
///
/// ^ y (1)
/// |
/// |
/// |
/// O------> x (1)
#[derive(Copy, Clone, Debug, PartialEq)]
struct OverlayUnit {
  rw: f32,
  rh: f32
}

impl OverlayUnit {
  pub fn new(w: u32, h: u32) -> Self {
    OverlayUnit {
      rw: 1. / (w as f32),
      rh: 1. / (h as f32)
    }
  }

  pub fn from_window(&self, x: u32, y: u32) -> [f32; 2] {
    let x_ = x as f32 * self.rw;
    assert!(x_ >= 0. && x_ <= 1., "x={}", x_);

    let y_ = y as f32 * self.rh;
    assert!(y_ >= 0. && y_ <= 1., "y={}", y_);

    [x_, y_]
  }
}
<commit_msg>Made overlay::RenderInput impl Clone.<commit_after>use luminance::{Dim2, Equation, Factor, Flat, Framebuffer, Mode, Pipe, Pipeline, RenderCommand, ShadingCommand, Tess, TessRender, TessVertices, Uniform, Unit, Vertex, VertexFormat};

use resource::Res;
use scene::Scene;
use shader::Program;
use text::TextTexture;
use texture::{RGBA32F, Texture};

/// Vertex used in overlay’s objects.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vert {
  /// Position.
  pub pos: [f32; 3],
  /// Color.
  pub color: [f32; 4]
}

impl Vert {
  pub fn new(pos: [f32; 3], color: [f32; 4]) -> Self {
    Vert {
      pos: pos,
      color: color
    }
  }
}

impl Vertex for Vert {
  fn vertex_format() -> VertexFormat {
    <([f32; 3], [f32; 4]) as Vertex>::vertex_format()
  }
}

pub struct Triangle(pub Vert, pub Vert, pub Vert);

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Disc {
  center: Vert,
  radius: f32
}

impl Disc {
  pub fn new(center: Vert, radius: f32) -> Self {
    Disc {
      center: center,
      radius: radius
    }
  }
}

impl Vertex for Disc {
  fn vertex_format() -> VertexFormat {
    <(Vert, f32) as Vertex>::vertex_format()
  }
}

pub type Texture2D = Texture<Flat, Dim2, RGBA32F>;

pub struct Text<'a> {
  text_texture: &'a TextTexture,
  left_upper: Vert
}

impl<'a> Text<'a> {
  pub fn new(text_texture: &'a TextTexture, left_upper: Vert) -> Self {
    Text {
      text_texture: text_texture,
      left_upper: left_upper
    }
  }
}

const DISC_SCREEN_RATIO: &'static Uniform<f32> = &Uniform::new(0);

const TEXT_SAMPLER: &'static Uniform<Unit> = &Uniform::new(0);
const TEXT_POS: &'static Uniform<[f32; 3]> = &Uniform::new(1);
const TEXT_SIZE: &'static Uniform<[f32; 2]> = &Uniform::new(2);
const TEXT_SCALE: &'static Uniform<f32> = &Uniform::new(3);
const TEXT_COLOR: &'static Uniform<[f32; 4]> = &Uniform::new(4);

/// A renderer responsible of rendering shapes.
pub struct Renderer {
  framebuffer: Framebuffer<Flat, Dim2, Texture2D, ()>,
  ratio: f32,
  tri_program: Res<Program>,
  tris: Tess,
  tri_vert_nb: usize,
  disc_program: Res<Program>,
  discs: Tess,
  disc_vert_nb: usize,
  text_program: Res<Program>,
  text_quad: Tess,
  overlay_unit: OverlayUnit,
}

impl Renderer {
  pub fn new(w: u32, h: u32, max_tris: usize, max_discs: usize, scene: &mut Scene) -> Self {
    let fb = Framebuffer::new((w, h), 0).unwrap();

    let tri_program = scene.get("spectra/overlay/triangle.glsl", vec![]).unwrap();
    let tris = Tess::new(Mode::Triangle, TessVertices::Reserve::<Vert>(max_tris * 3), None);

    let disc_program = scene.get("spectra/overlay/disc.glsl", vec![DISC_SCREEN_RATIO.sem("ratio")]).unwrap();
    let discs = Tess::new(Mode::Point, TessVertices::Reserve::<Disc>(max_discs), None);

    let text_program = scene.get("spectra/overlay/text.glsl", vec![
      TEXT_SAMPLER.sem("text_texture"),
      TEXT_POS.sem("pos"),
      TEXT_SIZE.sem("size"),
      TEXT_SCALE.sem("scale"),
      TEXT_COLOR.sem("color")
    ]).unwrap();

    let text_quad = Tess::attributeless(Mode::TriangleStrip, 4);

    Renderer {
      framebuffer: fb,
      ratio: w as f32 / h as f32,
      tri_program: tri_program,
      tris: tris,
      tri_vert_nb: 0,
      disc_program: disc_program,
      discs: discs,
      disc_vert_nb: 0,
      text_program: text_program,
      text_quad: text_quad,
      overlay_unit: OverlayUnit::new(w, h)
    }
  }

  fn dispatch(&mut self, input: &RenderInput) {
    let mut tris = self.tris.as_slice_mut().unwrap();
    let mut tri_i = 0;
    let mut discs = self.discs.as_slice_mut().unwrap();
    let mut disc_i = 0;

    for &Triangle(a, b, c) in input.triangles {
      tris[tri_i] = a;
      tri_i += 1;

      tris[tri_i] = b;
      tri_i += 1;

      tris[tri_i] = c;
      tri_i += 1;
    }

    for disc in input.discs {
      discs[disc_i] = *disc;
      disc_i += 1;
    }

    self.tri_vert_nb = tri_i;
    self.disc_vert_nb = disc_i;
  }

  pub fn render(&mut self, input: RenderInput) -> &Texture2D {
    self.dispatch(&input);

    let tris = TessRender::one_sub(&self.tris, self.tri_vert_nb);
    let discs = TessRender::one_sub(&self.discs, self.disc_vert_nb);
    let text_quad = TessRender::one_whole(&self.text_quad);

    // FIXME: no alloc?
    let text_uniforms: Vec<_> = input.texts.map(|(texts, text_scale)| texts.iter().map(|text| {
      let (tex_w, tex_h) = text.text_texture.size();

      [
        TEXT_SAMPLER.alter(Unit::new(0)),
        TEXT_POS.alter(text.left_upper.pos),
        TEXT_SIZE.alter(self.overlay_unit.from_window(tex_w, tex_h)),
        TEXT_SCALE.alter(text_scale),
        TEXT_COLOR.alter(text.left_upper.color),
      ]
    }).collect()).unwrap_or(Vec::new());

    let text_textures: Vec<_> = input.texts.map(|(texts, _)| texts.iter().map(|text| [&***text.text_texture]).collect()).unwrap_or(Vec::new());

    let text_render_cmds: Vec<_> = input.texts.iter().enumerate().map(|(i, _)| {
        let blending = (Equation::Additive, Factor::One, Factor::SrcAlphaComplement);
        Pipe::empty()
          .uniforms(&text_uniforms[i])
          .textures(&text_textures[i])
          .unwrap(RenderCommand::new(Some(blending), true, vec![
            Pipe::new(text_quad.clone())
          ]))
      }).collect();

    let disc_uniforms = [
      DISC_SCREEN_RATIO.alter(self.ratio)
    ];

    Pipeline::new(&self.framebuffer, [0., 0., 0., 0.], &[], &[], vec![
      // render triangles
      Pipe::new(ShadingCommand::new(&self.tri_program.borrow(), vec![
        Pipe::new(RenderCommand::new(None, true, vec![
          Pipe::new(tris)
        ]))
      ])),
      // render discs
      Pipe::empty()
        .uniforms(&disc_uniforms)
        .unwrap(ShadingCommand::new(&self.disc_program.borrow(), vec![
          Pipe::new(RenderCommand::new(None, true, vec![
            Pipe::new(discs)
          ]))
        ])),
      // render texts
      Pipe::new(ShadingCommand::new(&self.text_program.borrow(), text_render_cmds))
    ]).run();

    &self.framebuffer.color_slot
  }
}

#[derive(Clone)]
pub struct RenderInput<'a, 'b> where 'b: 'a {
  triangles: &'a [Triangle],
  discs: &'a [Disc],
  texts: Option<(&'a [Text<'b>], f32)>
}

impl<'a, 'b> RenderInput<'a, 'b> {
  pub fn new() -> Self {
    RenderInput {
      triangles: &[],
      discs: &[],
      texts: None,
    }
  }

  pub fn triangles(self, triangles: &'a [Triangle]) -> Self {
    RenderInput {
      triangles: triangles, ..self
    }
  }

  pub fn discs(self, discs: &'a [Disc]) -> Self {
    RenderInput {
      discs: discs,
      ..self
    }
  }

  pub fn texts(self, texts: &'a [Text<'b>], scale: f32) -> Self {
    RenderInput {
      texts: Some((texts, scale.max(0.))),
      ..self
    }
  }
}

/// Overlay units are used to position stuff in overlay in a universal way and screen independent
/// way. The screen uses normalized coordinates with the origin at lower left as the following
/// diagram:
///
/// ^ y (1)
/// |
/// |
/// |
/// O------> x (1)
#[derive(Copy, Clone, Debug, PartialEq)]
struct OverlayUnit {
  rw: f32,
  rh: f32
}

impl OverlayUnit {
  pub fn new(w: u32, h: u32) -> Self {
    OverlayUnit {
      rw: 1. / (w as f32),
      rh: 1. / (h as f32)
    }
  }

  pub fn from_window(&self, x: u32, y: u32) -> [f32; 2] {
    let x_ = x as f32 * self.rw;
    assert!(x_ >= 0. && x_ <= 1., "x={}", x_);

    let y_ = y as f32 * self.rh;
    assert!(y_ >= 0. && y_ <= 1., "y={}", y_);

    [x_, y_]
  }
}
<|endoftext|>


<commit_before>use std::path::Path;
use std::process::{Command, Output};
use std::io::Read;
use std::fs::File;
use copy_dir;
use shlex;

use errors::*;

/// Run a command, possibly in a specific directory. Using `format!(...)` to
/// turn the input tokens into a command string.
///
/// # Examples
///
/// ```rust,ignore
/// # use std::path::Path;
/// # #[macro_use]
/// # extern crate rustc_internal_docs;
/// let root = Path::new("/foo/bar/baz"):
/// cmd!(in root, "git pull {} {} --ff-only", "origin", "master")?;
/// ```
#[macro_export]
macro_rules! cmd {
    (in $dir:expr, $( $arg:expr ),+) => {
        $crate::helpers::execute_command(format!($( $arg ),*), Some($dir.as_ref()))
    };
    ($( $arg:expr ),+) => {
        $crate::helpers::execute_command(format!($( $arg ),*), None)
    };
}

/// Iterate through all the errors in an `error-chain`, printing them to the
/// screen and then bailing with an exit status of 1.
#[macro_export]
macro_rules! backtrace {
    ($maybe_err:expr) => {
        match $maybe_err {
            Ok(val) => val,
            Err(e) => {
                $crate::helpers::print_backtrace(&e, 0);
                ::std::process::exit(1);
            }
        }
    }
}

pub fn print_backtrace(e: &Error, indent: usize) {
    error!("{}Error: {}", "\t".repeat(indent), e);

    for cause in e.iter().skip(1) {
        error!("{}Caused By: {}", "\t".repeat(indent + 1), cause);
    }
}

/// Print either "" or " with return code 1", depending on whether we got a
/// return code.
pub fn pretty_print_return_code(code: Option<i32>) -> String {
    match code {
        None => String::new(),
        Some(i) => format!(" with return code {}", i),
    }
}

/// Print the stdout and stderr of a `std::process::Output` at the specified
/// logging level. The default is to print with `debug!()`.
macro_rules! print_output {
    ($output:expr) => { print_output!(debug, $output) };
    ($level:ident, $output:expr) => {{
        let output: &::std::process::Output = &$output;
        if !output.stdout.is_empty() {
            $level!("Stdout:");
            for line in String::from_utf8_lossy(&output.stdout).lines() {
                $level!("{}", line);
            }
        }
        if !output.stderr.is_empty() {
            $level!("Stderr:");
            for line in String::from_utf8_lossy(&output.stderr).lines() {
                $level!("{}", line);
            }
        }
    }}
}

/// Pretty much just `cp -r $from $to`.
pub fn recursive_copy<F: AsRef<Path>, T: AsRef<Path>>(from: F, to: T) -> Result<()> {
    let mut errors = copy_dir::copy_dir(from, to)?;
    if errors.is_empty() {
        Ok(())
    } else {
        // if there were any errors we'll blow up and pass it to the user
        let an_error = errors.pop().unwrap();
        bail!(an_error)
    }
}

pub fn execute_command<S: AsRef<str>>(cmd: S, cd_dir: Option<&Path>) -> Result<Output> {
    let cmd = cmd.as_ref();
    let parsed = match shlex::split(cmd) {
        Some(bits) => bits,
        None => bail!("Invalid command"),
    };

    if parsed.is_empty() {
        bail!("Can't execute an empty command");
    }

    let mut command_builder = Command::new(&parsed[0]);

    for arg in &parsed[1..] {
        command_builder.arg(arg);
    }

    if let Some(cd) = cd_dir {
        command_builder.current_dir(cd);
    }

    debug!(r#"Executing "{}""#, cmd);
    let output = command_builder
        .output()
        .chain_err(|| format!("Command not found, {}", parsed[0]))?;

    debug!(
        r#""{}" completed{}"#,
        cmd,
        pretty_print_return_code(output.status.code())
    );

    if !output.status.success() {
        warn!("Command failed: {}", cmd);
        print_output!(output);
        bail!(ErrorKind::CommandFailed(cmd.to_string(), output));
    }

    Ok(output)
}

/// Read a file's contents into memory.
pub fn read_file<P: AsRef<Path>>(filename: P) -> Result<String> {
    let filename = filename.as_ref();

    let mut buffer = String::new();
    File::open(filename)
        .chain_err(|| format!("Couldn't open {}", filename.display()))?
        .read_to_string(&mut buffer)
        .chain_err(|| "Couldn't read from the file")?;

    Ok((buffer))
}

#[cfg(test)]
mod tests {
    use super::*;
    use tempdir::TempDir;

    #[test]
    fn run_a_passing_command() {
        assert!(execute_command("true", None).is_ok());
    }

    #[test]
    fn run_a_failing_command() {
        assert!(execute_command("false", None).is_err());
    }

    #[test]
    fn detect_running_nonexistent_commands() {
        assert!(execute_command("foo bar baz", None).is_err());
    }

    #[test]
    fn macro_works_correctly_and_executes_in_a_directory() {
        let temp = TempDir::new("rustc-internal-docs").unwrap();
        let dummy_file = temp.path().join("dummy.txt");
        File::create(&dummy_file).unwrap();

        assert!(dummy_file.exists());
        cmd!(in temp.path(), "rm {}", dummy_file.display()).unwrap();
        assert!(!dummy_file.exists());
    }

    #[test]
    fn command_with_spaces_in_it() {
        let output = cmd!(r#"echo "Hello World""#).unwrap();

        let stdout = String::from_utf8_lossy(&output.stdout);
        assert!(stdout.contains("Hello World"));
        assert!(!stdout.contains('"'));
    }
}
<commit_msg>Toned down the logging a bit<commit_after>use std::path::Path;
use std::process::{Command, Output};
use std::io::Read;
use std::fs::File;
use copy_dir;
use shlex;

use errors::*;

/// Run a command, possibly in a specific directory. Using `format!(...)` to
/// turn the input tokens into a command string.
///
/// # Examples
///
/// ```rust,ignore
/// # use std::path::Path;
/// # #[macro_use]
/// # extern crate rustc_internal_docs;
/// let root = Path::new("/foo/bar/baz"):
/// cmd!(in root, "git pull {} {} --ff-only", "origin", "master")?;
/// ```
#[macro_export]
macro_rules! cmd {
    (in $dir:expr, $( $arg:expr ),+) => {
        $crate::helpers::execute_command(format!($( $arg ),*), Some($dir.as_ref()))
    };
    ($( $arg:expr ),+) => {
        $crate::helpers::execute_command(format!($( $arg ),*), None)
    };
}

/// Iterate through all the errors in an `error-chain`, printing them to the
/// screen and then bailing with an exit status of 1.
#[macro_export]
macro_rules! backtrace {
    ($maybe_err:expr) => {
        match $maybe_err {
            Ok(val) => val,
            Err(e) => {
                $crate::helpers::print_backtrace(&e, 0);
                ::std::process::exit(1);
            }
        }
    }
}

pub fn print_backtrace(e: &Error, indent: usize) {
    error!("{}Error: {}", "\t".repeat(indent), e);

    for cause in e.iter().skip(1) {
        error!("{}Caused By: {}", "\t".repeat(indent + 1), cause);
    }
}

/// Print either "" or " with return code 1", depending on whether we got a
/// return code.
pub fn pretty_print_return_code(code: Option<i32>) -> String {
    match code {
        None => String::new(),
        Some(i) => format!(" with return code {}", i),
    }
}

/// Print the stdout and stderr of a `std::process::Output` at the specified
/// logging level. The default is to print with `debug!()`.
macro_rules! print_output {
    ($output:expr) => { print_output!(debug, $output) };
    ($level:ident, $output:expr) => {{
        let output: &::std::process::Output = &$output;
        if !output.stdout.is_empty() {
            $level!("Stdout:");
            for line in String::from_utf8_lossy(&output.stdout).lines() {
                $level!("{}", line);
            }
        }
        if !output.stderr.is_empty() {
            $level!("Stderr:");
            for line in String::from_utf8_lossy(&output.stderr).lines() {
                $level!("{}", line);
            }
        }
    }}
}

/// Pretty much just `cp -r $from $to`.
pub fn recursive_copy<F: AsRef<Path>, T: AsRef<Path>>(from: F, to: T) -> Result<()> {
    let mut errors = copy_dir::copy_dir(from, to)?;
    if errors.is_empty() {
        Ok(())
    } else {
        // if there were any errors we'll blow up and pass it to the user
        let an_error = errors.pop().unwrap();
        bail!(an_error)
    }
}

pub fn execute_command<S: AsRef<str>>(cmd: S, cd_dir: Option<&Path>) -> Result<Output> {
    let cmd = cmd.as_ref();
    let parsed = match shlex::split(cmd) {
        Some(bits) => bits,
        None => bail!("Invalid command"),
    };

    if parsed.is_empty() {
        bail!("Can't execute an empty command");
    }

    let mut command_builder = Command::new(&parsed[0]);

    for arg in &parsed[1..] {
        command_builder.arg(arg);
    }

    if let Some(cd) = cd_dir {
        command_builder.current_dir(cd);
    }

    debug!(r#"Executing "{}""#, cmd);
    let output = command_builder
        .output()
        .chain_err(|| format!("Command not found, {}", parsed[0]))?;

    debug!(
        r#""{}" completed{}"#,
        cmd,
        pretty_print_return_code(output.status.code())
    );

    if !output.status.success() {
        warn!("Command failed: {}", cmd);
        print_output!(trace, output);
        bail!(ErrorKind::CommandFailed(cmd.to_string(), output));
    }

    Ok(output)
}

/// Read a file's contents into memory.
pub fn read_file<P: AsRef<Path>>(filename: P) -> Result<String> {
    let filename = filename.as_ref();

    let mut buffer = String::new();
    File::open(filename)
        .chain_err(|| format!("Couldn't open {}", filename.display()))?
        .read_to_string(&mut buffer)
        .chain_err(|| "Couldn't read from the file")?;

    Ok((buffer))
}

#[cfg(test)]
mod tests {
    use super::*;
    use tempdir::TempDir;

    #[test]
    fn run_a_passing_command() {
        assert!(execute_command("true", None).is_ok());
    }

    #[test]
    fn run_a_failing_command() {
        assert!(execute_command("false", None).is_err());
    }

    #[test]
    fn detect_running_nonexistent_commands() {
        assert!(execute_command("foo bar baz", None).is_err());
    }

    #[test]
    fn macro_works_correctly_and_executes_in_a_directory() {
        let temp = TempDir::new("rustc-internal-docs").unwrap();
        let dummy_file = temp.path().join("dummy.txt");
        File::create(&dummy_file).unwrap();

        assert!(dummy_file.exists());
        cmd!(in temp.path(), "rm {}", dummy_file.display()).unwrap();
        assert!(!dummy_file.exists());
    }

    #[test]
    fn command_with_spaces_in_it() {
        let output = cmd!(r#"echo "Hello World""#).unwrap();

        let stdout = String::from_utf8_lossy(&output.stdout);
        assert!(stdout.contains("Hello World"));
        assert!(!stdout.contains('"'));
    }
}
<|endoftext|>


<commit_before>// External modules:
use darwin_rs::{Individual, SimulationBuilder, Population, PopulationBuilder};
use image;
// use image::{GenericImage, FilterType, DynamicImage, imageops};
use image::{GenericImage, DynamicImage, Rgba};
use rand::Rng;
use rand;
use walkdir::{WalkDir};

// use std::path::Path;
use std::f64::consts::PI;
use std::cmp;
use std::sync::Arc;

// Internal modules:
use config::PanolutionConfig;

#[derive(Clone)]
pub struct ImageArrangement {
    pub image: Arc<DynamicImage>,
    pub full_path: String,
    pub samples: u32,
    pub x0: u32,
    pub y0: u32,
    pub x1: u32,
    pub y1: u32,
    pub angle: f64,
    // TODO: add more image operations
}

#[derive(Clone)]
pub struct Solution {
    pub arrangement: Vec<ImageArrangement>,
}

struct SamplePixel{
    x: u32,
    y: u32,
    pixels: Vec<(u8, u8, u8)>
}

fn valid_image_file(file_name: &str) -> bool {
    let extension = file_name.split(".").last().unwrap_or("").to_lowercase();

    let supported: Vec<String> = vec!["jpg", "jpeg", "gif", "png", "tif", "tiff"].iter().map(|s| s.to_string()).collect();

    supported.contains(&extension)
}

fn calc_canvas_size(arrangement: &Vec<ImageArrangement>) -> (u32, u32, u32, u32) {
    arrangement.iter().fold((u32::max_value(), u32::max_value(), 0, 0), |(cx0, cy0, cx1, cy1), im_ar| {
        (cmp::min(cx0, im_ar.x0), cmp::min(cy0, im_ar.y0), cmp::max(cx1, im_ar.x1), cmp::max(cy1, im_ar.y1))
    })
}

fn get_pixel(cx: f64, cy: f64, im_ar: &ImageArrangement) -> Option<(u8, u8, u8)> {
    // Center of image
    let mx = ((im_ar.x0 + im_ar.x1) / 2) as f64;
    let my = ((im_ar.y0 + im_ar.y1) / 2) as f64;

    // Move center of rotation to origin (0,0)
    let ox = cx - mx;
    let oy = cy - my;

    // Rotate canvas point in reverse of image orientation (clockwise)
    let cos_a = im_ar.angle.cos();
    let sin_a = im_ar.angle.sin();

    let rx = (ox * cos_a) + (oy * sin_a);
    let ry = (-ox * sin_a) + (oy * cos_a);

    // Move back to image coordinate system
    let imx = ((rx + mx) as u32) - im_ar.x0;
    let imy = ((ry + my) as u32) - im_ar.y0;

    // Check if point is inside the image:

    if (imx >= 0) && (imx < im_ar.image.width()) && (imy >= 0) && (imy < im_ar.image.height()) {
        let pixel = im_ar.image.get_pixel(imx, imy) as Rgba<u8>;
        return Some((pixel.data[0], pixel.data[1], pixel.data[2]));
    }

    None
}

fn make_all_populations(num_of_individuals: u32, num_of_populations: u32, initial_solution: &Solution) -> Vec<Population<Solution>> {
    let mut result = Vec::new();

    let mut initial_population = Vec::new();

    for _ in 0..num_of_individuals {
        initial_population.push(initial_solution.clone());
    }

    for i in 0..num_of_populations {
        let pop = PopulationBuilder::<Solution>::new()
            .set_id(i + 1)
            .initial_population(&initial_population)
            .reset_limit_end(0)
            .increasing_mutation_rate()
            .finalize().unwrap();

        result.push(pop);
    }

    result
}

impl Individual for Solution {
    fn mutate(&mut self) {
        let mut rng = rand::thread_rng();
        let num_of_operations: u8 = 4;

        let index1: usize = rng.gen_range(0, self.arrangement.len());

        // Probably use this create and enums for operation:
        // https://github.com/andersk/enum_primitive-rs
        let operation: u8 = rng.gen_range(0, num_of_operations);

        match operation {
            0 => {
                // Change image order
                let mut index2: usize = rng.gen_range(0, self.arrangement.len());
                while index1 == index2 {
                    index2 = rng.gen_range(0, self.arrangement.len());
                }

                let px0 = self.arrangement[index1].x0;
                let py0 = self.arrangement[index1].y0;
                let px1 = self.arrangement[index1].x1;
                let py1 = self.arrangement[index1].y1;

                self.arrangement[index1].x0 = self.arrangement[index2].x0;
                self.arrangement[index1].y0 = self.arrangement[index2].y0;
                self.arrangement[index1].x1 = self.arrangement[index2].x1;
                self.arrangement[index1].y1 = self.arrangement[index2].y1;

                self.arrangement[index2].x0 = px0;
                self.arrangement[index2].y0 = py0;
                self.arrangement[index2].x1 = px1;
                self.arrangement[index2].y1 = py1;
            },
            1 => {
                // Move x
                let dx = rng.gen_range::<i32>(0, 500) - 250;
                let new_x = (self.arrangement[index1].x0 as i32) + dx;

                if new_x >= 0 {
                    self.arrangement[index1].x0 = new_x as u32;
                    self.arrangement[index1].x1 = ((self.arrangement[index1].x1 as i32) + dx) as u32;
                }
            },
            2 => {
                // Move y
                let dy = rng.gen_range::<i32>(0, 500) - 250;
                let new_y = (self.arrangement[index1].y0 as i32) + dy;

                if new_y >= 0 {
                    self.arrangement[index1].y0 = new_y as u32;
                    self.arrangement[index1].y1 = ((self.arrangement[index1].y1 as i32) + dy) as u32;
                }
            },
            3 => {
                // Rotate
                self.arrangement[index1].angle = self.arrangement[index1].angle + (rng.next_f64() * 0.1);
                if self.arrangement[index1].angle < 0.0 {
                    self.arrangement[index1].angle = 0.0;
                } else if self.arrangement[index1].angle > 2.0 * PI {
                    self.arrangement[index1].angle = 0.0;
                }
            },
            op => {
                warn!("mutate(): unknown operation: {}", op)
            }
        }
    }

    fn calculate_fitness(&mut self) -> f64 {
        let num_of_samples = self.arrangement[0].samples;

        let (cx0, cy0, cx1, cy1) = calc_canvas_size(&self.arrangement);

        // Create sample points on canvas:
        let mut rng = rand::thread_rng();
        let mut sample_pixels = Vec::new();

        for _ in 0..num_of_samples {
            sample_pixels.push(SamplePixel{
                x: rng.gen_range::<u32>(cx0, cx1),
                y: rng.gen_range::<u32>(cy0, cy1),
                pixels: Vec::new()
            });
        }

        for im_ar in &self.arrangement {
            for sp in &mut sample_pixels {
                if let Some(pixel) = get_pixel(sp.x as f64, sp.y as f64, &im_ar) {
                    sp.pixels.push(pixel);
                }
            }
        }

        let error_sum = sample_pixels.iter().fold(0_u32, |sum, sp| {
            if sp.pixels.len() > 0 {
                let r0 = sp.pixels[0].0;
                let g0 = sp.pixels[0].1;
                let b0 = sp.pixels[0].2;
                let max_diff = sp.pixels.iter().fold((0_u32, r0, g0, b0), |(diff, r1, g1, b1), &(r2, g2, b2)| {
                    let rdiff = if r1 > r2 {r1 - r2} else {r2 - r1};
                    let gdiff  = if g1 > g2 {g1 - g2} else {g2 - g1};
                    let bdiff  = if b1 > b2 {b1 - b2} else {b2 - b1};

                    (cmp::max(diff, (rdiff as u32) + (gdiff as u32) + (bdiff as u32)), r2, g2, b2)
                });
                sum + max_diff.0
            } else {
                // Add penalty if the images do not overlap
                sum + 255
            }

        });

        (error_sum as f64) / (num_of_samples as f64)
    }

    fn reset(&mut self) {
        for arrangement in &mut self.arrangement {
            // Reset all image operation to original image
            arrangement.x1 = arrangement.x1 - arrangement.x0;
            arrangement.y1 = arrangement.y1 - arrangement.y0;
            arrangement.x0 = 0;
            arrangement.y0 = 0;
            arrangement.angle = 0.0;
        }
    }
}

fn run_darwin(solution: &Solution, config: &PanolutionConfig) -> Solution {
    let pano = SimulationBuilder::<Solution>::new()
        .iterations(config.max_iteration)
        .threads(4)
        .output_every(0)
        .add_multiple_populations(make_all_populations(20, 8, &solution))
        .finalize();

    match pano {
        Err(e) => {
            error!("An error occured");

            for e in e.iter().skip(1) {
                error!("Caused by '{}'", e)
            }

            solution.clone()
        },
        Ok(mut pano_simulation) => {
            pano_simulation.run();

            info!("Total run time: {} ms", pano_simulation.total_time_in_ms);
            info!("Improvement factor: {}", pano_simulation.simulation_result.improvement_factor);
            info!("Number of iterations: {}", pano_simulation.simulation_result.iteration_counter);
            info!("New fitness: {}", pano_simulation.simulation_result.fittest[0].fitness);

            pano_simulation.simulation_result.fittest[0].individual.clone()
        }
    }
}

pub fn optimize(solution: Option<&Solution>, config: &PanolutionConfig, sample_index: usize) -> Solution {
    match solution {
        None => {
            let mut arrangement = Vec::new();

            for entry in WalkDir::new(&config.input_path) {
                if let Ok(entry) = entry {
                    if entry.file_type().is_file() {
                        if let Some(file_name) = entry.file_name().to_str() {
                            if valid_image_file(file_name) {
                                if let Some(full_path) = entry.path().to_str() {

                                    if let Ok(img) = image::open(&full_path) {
                                        arrangement.push(ImageArrangement{
                                            image: Arc::new(img.clone()),
                                            full_path: full_path.to_string(),
                                            samples: config.num_of_samples[sample_index],
                                            x0: 0,
                                            y0: 0,
                                            x1: img.width(),
                                            y1: img.height(),
                                            angle: 0.0,
                                        });
                                    } else {
                                        error!("Could not open image: {}", full_path)
                                    }
                                } else {
                                    error!("Could not convert full path to str: {:?}", entry);
                                }
                            } else {
                                error!("Image format currently not supported: {}", file_name);
                            }
                        } else {
                            error!("Could not convert file name to str: {:?}", entry);
                        }
                    } else {
                        info!("Ignore non-file: {:?}", entry);
                    }
                } else {
                    error!("Error in WalkDir");
                }
            }

            let solution = Solution{arrangement: arrangement};

            if solution.arrangement.len() > 0 {
                run_darwin(&solution, &config)
            } else {
                // An error occured
                // TODO: return Result<Soultion> and use chain_err
                solution
            }
        },
        Some(solution) => {
            let mut updated_arrangement = solution.arrangement.clone();

            for im_ar in &mut updated_arrangement {
                im_ar.samples = config.num_of_samples[sample_index];
            }

            run_darwin(&Solution{arrangement: updated_arrangement}, &config)
        }
    }
}
<commit_msg>restructure penalty if there is no overlap<commit_after>// External modules:
use darwin_rs::{Individual, SimulationBuilder, Population, PopulationBuilder};
use image;
// use image::{GenericImage, FilterType, DynamicImage, imageops};
use image::{GenericImage, DynamicImage, Rgba};
use rand::Rng;
use rand;
use walkdir::{WalkDir};

// use std::path::Path;
use std::f64::consts::PI;
use std::cmp;
use std::sync::Arc;

// Internal modules:
use config::PanolutionConfig;

#[derive(Clone)]
pub struct ImageArrangement {
    pub image: Arc<DynamicImage>,
    pub full_path: String,
    pub samples: u32,
    pub x0: u32,
    pub y0: u32,
    pub x1: u32,
    pub y1: u32,
    pub angle: f64,
    // TODO: add more image operations
}

#[derive(Clone)]
pub struct Solution {
    pub arrangement: Vec<ImageArrangement>,
}

struct SamplePixel{
    x: u32,
    y: u32,
    pixels: Vec<(u8, u8, u8)>
}

fn valid_image_file(file_name: &str) -> bool {
    let extension = file_name.split(".").last().unwrap_or("").to_lowercase();

    let supported: Vec<String> = vec!["jpg", "jpeg", "gif", "png", "tif", "tiff"].iter().map(|s| s.to_string()).collect();

    supported.contains(&extension)
}

fn calc_canvas_size(arrangement: &Vec<ImageArrangement>) -> (u32, u32, u32, u32) {
    arrangement.iter().fold((u32::max_value(), u32::max_value(), 0, 0), |(cx0, cy0, cx1, cy1), im_ar| {
        (cmp::min(cx0, im_ar.x0), cmp::min(cy0, im_ar.y0), cmp::max(cx1, im_ar.x1), cmp::max(cy1, im_ar.y1))
    })
}

fn get_pixel(cx: f64, cy: f64, im_ar: &ImageArrangement) -> Option<(u8, u8, u8)> {
    // Center of image
    let mx = ((im_ar.x0 + im_ar.x1) / 2) as f64;
    let my = ((im_ar.y0 + im_ar.y1) / 2) as f64;

    // Move center of rotation to origin (0,0)
    let ox = cx - mx;
    let oy = cy - my;

    // Rotate canvas point in reverse of image orientation (clockwise)
    let cos_a = im_ar.angle.cos();
    let sin_a = im_ar.angle.sin();

    let rx = (ox * cos_a) + (oy * sin_a);
    let ry = (-ox * sin_a) + (oy * cos_a);

    // Move back to image coordinate system
    let imx = ((rx + mx) as u32) - im_ar.x0;
    let imy = ((ry + my) as u32) - im_ar.y0;

    // Check if point is inside the image:

    if (imx >= 0) && (imx < im_ar.image.width()) && (imy >= 0) && (imy < im_ar.image.height()) {
        let pixel = im_ar.image.get_pixel(imx, imy) as Rgba<u8>;
        return Some((pixel.data[0], pixel.data[1], pixel.data[2]));
    }

    None
}

fn make_all_populations(num_of_individuals: u32, num_of_populations: u32, initial_solution: &Solution) -> Vec<Population<Solution>> {
    let mut result = Vec::new();

    let mut initial_population = Vec::new();

    for _ in 0..num_of_individuals {
        initial_population.push(initial_solution.clone());
    }

    for i in 0..num_of_populations {
        let pop = PopulationBuilder::<Solution>::new()
            .set_id(i + 1)
            .initial_population(&initial_population)
            .reset_limit_end(0)
            .increasing_mutation_rate()
            .finalize().unwrap();

        result.push(pop);
    }

    result
}

impl Individual for Solution {
    fn mutate(&mut self) {
        let mut rng = rand::thread_rng();
        let num_of_operations: u8 = 4;

        let index1: usize = rng.gen_range(0, self.arrangement.len());

        // Probably use this create and enums for operation:
        // https://github.com/andersk/enum_primitive-rs
        let operation: u8 = rng.gen_range(0, num_of_operations);

        match operation {
            0 => {
                // Change image order
                let mut index2: usize = rng.gen_range(0, self.arrangement.len());
                while index1 == index2 {
                    index2 = rng.gen_range(0, self.arrangement.len());
                }

                let px0 = self.arrangement[index1].x0;
                let py0 = self.arrangement[index1].y0;
                let px1 = self.arrangement[index1].x1;
                let py1 = self.arrangement[index1].y1;

                self.arrangement[index1].x0 = self.arrangement[index2].x0;
                self.arrangement[index1].y0 = self.arrangement[index2].y0;
                self.arrangement[index1].x1 = self.arrangement[index2].x1;
                self.arrangement[index1].y1 = self.arrangement[index2].y1;

                self.arrangement[index2].x0 = px0;
                self.arrangement[index2].y0 = py0;
                self.arrangement[index2].x1 = px1;
                self.arrangement[index2].y1 = py1;
            },
            1 => {
                // Move x
                let dx = rng.gen_range::<i32>(0, 500) - 250;
                let new_x = (self.arrangement[index1].x0 as i32) + dx;

                if new_x >= 0 {
                    self.arrangement[index1].x0 = new_x as u32;
                    self.arrangement[index1].x1 = ((self.arrangement[index1].x1 as i32) + dx) as u32;
                }
            },
            2 => {
                // Move y
                let dy = rng.gen_range::<i32>(0, 500) - 250;
                let new_y = (self.arrangement[index1].y0 as i32) + dy;

                if new_y >= 0 {
                    self.arrangement[index1].y0 = new_y as u32;
                    self.arrangement[index1].y1 = ((self.arrangement[index1].y1 as i32) + dy) as u32;
                }
            },
            3 => {
                // Rotate
                self.arrangement[index1].angle = self.arrangement[index1].angle + (rng.next_f64() * 0.1);
                if self.arrangement[index1].angle < 0.0 {
                    self.arrangement[index1].angle = 0.0;
                } else if self.arrangement[index1].angle > 2.0 * PI {
                    self.arrangement[index1].angle = 0.0;
                }
            },
            op => {
                warn!("mutate(): unknown operation: {}", op)
            }
        }
    }

    fn calculate_fitness(&mut self) -> f64 {
        let num_of_samples = self.arrangement[0].samples;

        let (cx0, cy0, cx1, cy1) = calc_canvas_size(&self.arrangement);

        // Create sample points on canvas:
        let mut rng = rand::thread_rng();
        let mut sample_pixels = Vec::new();

        for _ in 0..num_of_samples {
            sample_pixels.push(SamplePixel{
                x: rng.gen_range::<u32>(cx0, cx1),
                y: rng.gen_range::<u32>(cy0, cy1),
                pixels: Vec::new()
            });
        }

        for im_ar in &self.arrangement {
            for sp in &mut sample_pixels {
                if let Some(pixel) = get_pixel(sp.x as f64, sp.y as f64, &im_ar) {
                    sp.pixels.push(pixel);
                }
            }
        }

        let error_sum = sample_pixels.iter().fold(0_u32, |sum, sp| {
            let num_of_pixels = sp.pixels.len();

            if num_of_pixels == 0 {
                // No pixel at all, random sample is outside of any image
                sum
            } else if num_of_pixels == 1 {
                // No overlap, add penalty
                sum + 255
            } else {
                let r0 = sp.pixels[0].0;
                let g0 = sp.pixels[0].1;
                let b0 = sp.pixels[0].2;
                let max_diff = sp.pixels.iter().fold((0_u32, r0, g0, b0), |(diff, r1, g1, b1), &(r2, g2, b2)| {
                    let rdiff = if r1 > r2 {r1 - r2} else {r2 - r1};
                    let gdiff  = if g1 > g2 {g1 - g2} else {g2 - g1};
                    let bdiff  = if b1 > b2 {b1 - b2} else {b2 - b1};

                    (cmp::max(diff, (rdiff as u32) + (gdiff as u32) + (bdiff as u32)), r2, g2, b2)
                });
                sum + max_diff.0
            }

        });

        (error_sum as f64) / (num_of_samples as f64)
    }

    fn reset(&mut self) {
        for arrangement in &mut self.arrangement {
            // Reset all image operation to original image
            arrangement.x1 = arrangement.x1 - arrangement.x0;
            arrangement.y1 = arrangement.y1 - arrangement.y0;
            arrangement.x0 = 0;
            arrangement.y0 = 0;
            arrangement.angle = 0.0;
        }
    }
}

fn run_darwin(solution: &Solution, config: &PanolutionConfig) -> Solution {
    let pano = SimulationBuilder::<Solution>::new()
        .iterations(config.max_iteration)
        .threads(4)
        .output_every(0)
        .add_multiple_populations(make_all_populations(20, 8, &solution))
        .finalize();

    match pano {
        Err(e) => {
            error!("An error occured");

            for e in e.iter().skip(1) {
                error!("Caused by '{}'", e)
            }

            solution.clone()
        },
        Ok(mut pano_simulation) => {
            pano_simulation.run();

            info!("Total run time: {} ms", pano_simulation.total_time_in_ms);
            info!("Improvement factor: {}", pano_simulation.simulation_result.improvement_factor);
            info!("Number of iterations: {}", pano_simulation.simulation_result.iteration_counter);
            info!("New fitness: {}", pano_simulation.simulation_result.fittest[0].fitness);

            pano_simulation.simulation_result.fittest[0].individual.clone()
        }
    }
}

pub fn optimize(solution: Option<&Solution>, config: &PanolutionConfig, sample_index: usize) -> Solution {
    match solution {
        None => {
            let mut arrangement = Vec::new();

            for entry in WalkDir::new(&config.input_path) {
                if let Ok(entry) = entry {
                    if entry.file_type().is_file() {
                        if let Some(file_name) = entry.file_name().to_str() {
                            if valid_image_file(file_name) {
                                if let Some(full_path) = entry.path().to_str() {

                                    if let Ok(img) = image::open(&full_path) {
                                        arrangement.push(ImageArrangement{
                                            image: Arc::new(img.clone()),
                                            full_path: full_path.to_string(),
                                            samples: config.num_of_samples[sample_index],
                                            x0: 0,
                                            y0: 0,
                                            x1: img.width(),
                                            y1: img.height(),
                                            angle: 0.0,
                                        });
                                    } else {
                                        error!("Could not open image: {}", full_path)
                                    }
                                } else {
                                    error!("Could not convert full path to str: {:?}", entry);
                                }
                            } else {
                                error!("Image format currently not supported: {}", file_name);
                            }
                        } else {
                            error!("Could not convert file name to str: {:?}", entry);
                        }
                    } else {
                        info!("Ignore non-file: {:?}", entry);
                    }
                } else {
                    error!("Error in WalkDir");
                }
            }

            let solution = Solution{arrangement: arrangement};

            if solution.arrangement.len() > 0 {
                run_darwin(&solution, &config)
            } else {
                // An error occured
                // TODO: return Result<Soultion> and use chain_err
                solution
            }
        },
        Some(solution) => {
            let mut updated_arrangement = solution.arrangement.clone();

            for im_ar in &mut updated_arrangement {
                im_ar.samples = config.num_of_samples[sample_index];
            }

            run_darwin(&Solution{arrangement: updated_arrangement}, &config)
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The Rust Project Developers.
// Copyright 2018 The Uuid Project Developers.
//
// See the COPYRIGHT file at the top-level directory of this distribution.
//
// 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.

//! The [`uuid`] prelude.
//!
//! This module contains the most important items of the [`uuid`] crate.
//!
//! To use the prelude, include the following in your crate root:
//!
//! ```rust
//! extern crate uuid;
//! ```
//!
//! and the following in every module:
//!
//! ```rust
//! use uuid::prelude::*;
//! ```
//!
//! # Prelude Contents
//!
//! Currently the prelude reexports the following:
//!
//! [`uuid`]`::{`[`Uuid`], [`Variant`], [`Version`]`}`: The fundamental
//! types used in [`uuid`] crate.
//!
//! [`uuid`]: ../index.html
//! [`Uuid`]: ../struct.Uuid.html
//! [`Variant`]: ../enum.Variant.html
//! [`Version`]: ../enum.Version.html
//!
#![cfg_attr(feature = "v1",
doc = "
[`uuid::v1`]`::{`[`ClockSequence`],[`Context`]`}`: The types useful for
handling uuid version 1. Requires feature `v1`.

[`uuid::v1`]: ../v1/index.html
[`Context`]: ../v1/struct.Context.html
[`ClockSequence`]: ../v1/trait.ClockSequence.html")]

#[doc(inline)]
pub use super::{Bytes, Uuid, Variant, Version};
#[cfg(feature = "v1")]
#[doc(inline)]
pub use v1::{ClockSequence, Context};
<commit_msg>don't inline the prelude items.<commit_after>// Copyright 2013-2014 The Rust Project Developers.
// Copyright 2018 The Uuid Project Developers.
//
// See the COPYRIGHT file at the top-level directory of this distribution.
//
// 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.

//! The [`uuid`] prelude.
//!
//! This module contains the most important items of the [`uuid`] crate.
//!
//! To use the prelude, include the following in your crate root:
//!
//! ```rust
//! extern crate uuid;
//! ```
//!
//! and the following in every module:
//!
//! ```rust
//! use uuid::prelude::*;
//! ```
//!
//! # Prelude Contents
//!
//! Currently the prelude reexports the following:
//!
//! [`uuid`]`::{`[`Uuid`], [`Variant`], [`Version`]`}`: The fundamental
//! types used in [`uuid`] crate.
//!
//! [`uuid`]: ../index.html
//! [`Uuid`]: ../struct.Uuid.html
//! [`Variant`]: ../enum.Variant.html
//! [`Version`]: ../enum.Version.html
//!
#![cfg_attr(feature = "v1",
doc = "
[`uuid::v1`]`::{`[`ClockSequence`],[`Context`]`}`: The types useful for
handling uuid version 1. Requires feature `v1`.

[`uuid::v1`]: ../v1/index.html
[`Context`]: ../v1/struct.Context.html
[`ClockSequence`]: ../v1/trait.ClockSequence.html")]

pub use super::{Bytes, Uuid, Variant, Version};
#[cfg(feature = "v1")]
pub use v1::{ClockSequence, Context};
<|endoftext|>


<commit_before>use std::path::PathBuf;

pub use self::imp::*;

#[cfg(target_family = "unix")]
mod imp {
    use std::io::Result;
    use std::path::PathBuf;
    use std::process::Command;

    pub struct Process {
        pid: i32,
    }

    impl Process {
        pub fn new(cmd: &str, updated_paths: Vec<PathBuf>) -> Result<Process> {
            use std::io;
            use std::os::unix::process::CommandExt;
            use libc::exit;
            use nix::unistd::*;

            let mut command = Command::new("sh");
            command.arg("-c").arg(cmd);

            if let Some(single_path) = super::get_single_updated_path(&updated_paths) {
                command.env("WATCHEXEC_UPDATED_PATH", single_path);
            }

            if let Some(common_path) = super::get_longest_common_path(&updated_paths) {
                command.env("WATCHEXEC_COMMON_PATH", common_path);
            }

            // Until process_exec lands in stable, handle fork/exec ourselves
            //command.before_exec(|| setpgid(0, 0).map_err(io::Error::from))
                //.spawn()
                //.and_then(|p| Ok(Process { pid: p.id() as i32 }))

            match fork() {
                Ok(ForkResult::Parent {child, .. }) => {
                    Ok(Process {
                        pid: child as i32
                    })
                },
                Ok(ForkResult::Child) => {
                    let _ = setpgid(0, 0);
                    let _ = command.exec();

                    // If we get here, there isn't much we can do
                    unsafe {
                        exit(1);
                    }
                }
                Err(e) => { Err(io::Error::from(e)) }
            }
        }

        pub fn kill(&self) {
            use libc;

            extern "C" {
                fn killpg(pgrp: libc::pid_t, sig: libc::c_int) -> libc::c_int;
            }

            unsafe {
                killpg(self.pid, libc::SIGTERM);
            }
        }

        pub fn wait(&self) {
            use nix::sys::wait::waitpid;

            let _ = waitpid(self.pid, None);
        }
    }
}

#[cfg(target_family = "windows")]
mod imp {
    use std::io;
    use std::io::Result;
    use std::mem;
    use std::path::PathBuf;
    use std::process::Command;
    use kernel32::*;
    use winapi::*;

    pub struct Process {
        job: HANDLE,
    }

    impl Process {
        pub fn new(cmd: &str, updated_paths: Vec<PathBuf>) -> Result<Process> {
            use std::os::windows::io::IntoRawHandle;

            fn last_err() -> io::Error {
                io::Error::last_os_error()
            }

            let job = unsafe { CreateJobObjectW(0 as *mut _, 0 as *const _) };
            if job.is_null() {
                panic!("failed to create job object: {}", last_err());
            }

            let mut info: JOBOBJECT_EXTENDED_LIMIT_INFORMATION = unsafe { mem::zeroed() };
            info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
            let r = unsafe {
                SetInformationJobObject(job,
                                        JobObjectExtendedLimitInformation,
                                        &mut info as *mut _ as LPVOID,
                                        mem::size_of_val(&info) as DWORD)
            };
            if r == 0 {
                panic!("failed to set job info: {}", last_err());
            }

            let mut command = Command::new("cmd.exe");
            command.arg("/C").arg(cmd);

            if let Some(single_path) = super::get_single_updated_path(&updated_paths) {
                command.env("WATCHEXEC_UPDATED_PATH", single_path);
            }

            if let Some(common_path) = super::get_longest_common_path(&updated_paths) {
                command.env("WATCHEXEC_COMMON_PATH", common_path);
            }

            command.spawn()
                .and_then(|p| {
                    let r = unsafe { AssignProcessToJobObject(job, p.into_raw_handle()) };
                    if r == 0 {
                        panic!("failed to add to job object: {}", last_err());
                    }

                    Ok(Process { job: job })
                })
        }

        pub fn kill(&self) {
            unsafe {
                let _ = TerminateJobObject(self.job, 1);
            }
        }

        pub fn wait(&self) {
            unsafe {
                let _ = WaitForSingleObject(self.job, INFINITE);
            }
        }
    }

    impl Drop for Process {
        fn drop(&mut self) {
            unsafe {
                let _ = CloseHandle(self.job);
            }
        }
    }

    unsafe impl Send for Process {}
    unsafe impl Sync for Process {}
}

fn get_single_updated_path(paths: &[PathBuf]) -> Option<&str> {
    paths.get(0).and_then(|p| p.to_str())
}

fn get_longest_common_path(paths: &[PathBuf]) -> Option<String> {
    match paths.len() {
        0 => return None,
        1 => return paths[0].to_str().map(|ref_val| ref_val.to_string()),
        _ => {}
    };

    let mut longest_path: Vec<_> = paths[0].components().collect();

    for path in &paths[1..] {
        let mut greatest_distance = 0;
        for component_pair in path.components().zip(longest_path.iter()) {
            if component_pair.0 != *component_pair.1 {
                break;
            }

            greatest_distance += 1;
        }

        if greatest_distance != longest_path.len() {
            longest_path.truncate(greatest_distance);
        }
    }

    let mut result = PathBuf::new();
    for component in longest_path {
        result.push(component.as_os_str());
    }

    result.to_str().map(|ref_val| ref_val.to_string())
}

#[cfg(test)]
#[cfg(target_family = "unix")]
mod tests {
    use std::path::{Path, PathBuf};
    use std::thread;
    use std::time::Duration;

    use mktemp::Temp;

    use super::imp::Process;
    use super::get_longest_common_path;

    fn file_contents(path: &Path) -> String {
        use std::fs::File;
        use std::io::Read;

        let mut f = File::open(path).unwrap();
        let mut s = String::new();
        f.read_to_string(&mut s).unwrap();

        s
    }

    #[test]
    fn test_start() {
        let process = Process::new("echo hi", vec![]);

        assert!(process.is_ok());
    }

    #[test]
    fn test_wait() {
        let file = Temp::new_file().unwrap();
        let path = file.to_path_buf();
        let process = Process::new(&format!("echo hi > {}", path.to_str().unwrap()), vec![])
            .unwrap();
        process.wait();

        assert!(file_contents(&path).starts_with("hi"));
    }

    #[test]
    fn test_kill() {
        let file = Temp::new_file().unwrap();
        let path = file.to_path_buf();

        let process = Process::new(&format!("sleep 20; echo hi > {}", path.to_str().unwrap()),
                                       vec![])
            .unwrap();
        thread::sleep(Duration::from_millis(250));
        process.kill();
        process.wait();

        assert!(file_contents(&path) == "");
    }

    #[test]
    fn longest_common_path_should_return_correct_value() {
        let single_path = vec![PathBuf::from("/tmp/random/")];
        let single_result = get_longest_common_path(&single_path).unwrap();
        assert_eq!(single_result, "/tmp/random/");

        let common_paths = vec![PathBuf::from("/tmp/logs/hi"),
                                PathBuf::from("/tmp/logs/bye"),
                                PathBuf::from("/tmp/logs/bye"),
                                PathBuf::from("/tmp/logs/fly")];

        let common_result = get_longest_common_path(&common_paths).unwrap();
        assert_eq!(common_result, "/tmp/logs");

        let diverging_paths = vec![PathBuf::from("/tmp/logs/hi"), PathBuf::from("/var/logs/hi")];

        let diverging_result = get_longest_common_path(&diverging_paths).unwrap();
        assert_eq!(diverging_result, "/");

        let uneven_paths = vec![PathBuf::from("/tmp/logs/hi"),
                                PathBuf::from("/tmp/logs/"),
                                PathBuf::from("/tmp/logs/bye")];

        let uneven_result = get_longest_common_path(&uneven_paths).unwrap();
        assert_eq!(uneven_result, "/tmp/logs");
    }
}
<commit_msg>Fix setpgid() racing killpg()/waitpid() in tests<commit_after>use std::path::PathBuf;

pub use self::imp::*;

#[cfg(target_family = "unix")]
mod imp {
    use libc::pid_t;
    use std::io::Result;
    use std::path::PathBuf;
    use std::process::Command;

    pub struct Process {
        pgid: pid_t,
    }

    impl Process {
        pub fn new(cmd: &str, updated_paths: Vec<PathBuf>) -> Result<Process> {
            use libc::exit;
            use nix::unistd::*;
            use std::io;
            use std::os::unix::process::CommandExt;

            let mut command = Command::new("sh");
            command.arg("-c").arg(cmd);

            if let Some(single_path) = super::get_single_updated_path(&updated_paths) {
                command.env("WATCHEXEC_UPDATED_PATH", single_path);
            }

            if let Some(common_path) = super::get_longest_common_path(&updated_paths) {
                command.env("WATCHEXEC_COMMON_PATH", common_path);
            }

            // Until process_exec lands in stable, handle fork/exec ourselves
            //command.before_exec(|| setpgid(0, 0).map_err(io::Error::from))
                //.spawn()
                //.and_then(|p| Ok(Process { pid: p.id() as i32 }))

            // Wait for child to call setpgid()
            // Else, we risk racing waitpid/killpg (mostly just in tests, but hey)
            let (r, w) = try!(pipe());

            match fork() {
                Ok(ForkResult::Parent {child, .. }) => {
                    let mut buffer = vec![0];
                    let _ = read(r, &mut buffer);
                    let _ = close(r);
                    let _ = close(w);

                    Ok(Process {
                        pgid: child
                    })
                },
                Ok(ForkResult::Child) => {
                    let _ = setpgid(0, 0);

                    let _ = write(w, &[42]);
                    let _ = close(w);
                    let _ = close(r);

                    let _ = command.exec();

                    // If we get here, there isn't much we can do
                    unsafe {
                        exit(1);
                    }
                }
                Err(e) => { Err(io::Error::from(e)) }
            }
        }

        pub fn kill(&self) {
            use libc::*;

            extern "C" {
                fn killpg(pgrp: pid_t, sig: c_int) -> c_int;
            }

            unsafe {
                killpg(self.pgid, SIGTERM);
            }
        }

        pub fn wait(&self) {
            use nix::sys::wait::waitpid;

            while let Ok(_) = waitpid(-self.pgid, None) {}
        }
    }
}

#[cfg(target_family = "windows")]
mod imp {
    use std::io;
    use std::io::Result;
    use std::mem;
    use std::path::PathBuf;
    use std::process::Command;
    use kernel32::*;
    use winapi::*;

    pub struct Process {
        job: HANDLE,
    }

    impl Process {
        pub fn new(cmd: &str, updated_paths: Vec<PathBuf>) -> Result<Process> {
            use std::os::windows::io::IntoRawHandle;

            fn last_err() -> io::Error {
                io::Error::last_os_error()
            }

            let job = unsafe { CreateJobObjectW(0 as *mut _, 0 as *const _) };
            if job.is_null() {
                panic!("failed to create job object: {}", last_err());
            }

            let mut info: JOBOBJECT_EXTENDED_LIMIT_INFORMATION = unsafe { mem::zeroed() };
            info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
            let r = unsafe {
                SetInformationJobObject(job,
                                        JobObjectExtendedLimitInformation,
                                        &mut info as *mut _ as LPVOID,
                                        mem::size_of_val(&info) as DWORD)
            };
            if r == 0 {
                panic!("failed to set job info: {}", last_err());
            }

            let mut command = Command::new("cmd.exe");
            command.arg("/C").arg(cmd);

            if let Some(single_path) = super::get_single_updated_path(&updated_paths) {
                command.env("WATCHEXEC_UPDATED_PATH", single_path);
            }

            if let Some(common_path) = super::get_longest_common_path(&updated_paths) {
                command.env("WATCHEXEC_COMMON_PATH", common_path);
            }

            command.spawn()
                .and_then(|p| {
                    let r = unsafe { AssignProcessToJobObject(job, p.into_raw_handle()) };
                    if r == 0 {
                        panic!("failed to add to job object: {}", last_err());
                    }

                    Ok(Process { job: job })
                })
        }

        pub fn kill(&self) {
            unsafe {
                let _ = TerminateJobObject(self.job, 1);
            }
        }

        pub fn wait(&self) {
            unsafe {
                let _ = WaitForSingleObject(self.job, INFINITE);
            }
        }
    }

    impl Drop for Process {
        fn drop(&mut self) {
            unsafe {
                let _ = CloseHandle(self.job);
            }
        }
    }

    unsafe impl Send for Process {}
    unsafe impl Sync for Process {}
}

fn get_single_updated_path(paths: &[PathBuf]) -> Option<&str> {
    paths.get(0).and_then(|p| p.to_str())
}

fn get_longest_common_path(paths: &[PathBuf]) -> Option<String> {
    match paths.len() {
        0 => return None,
        1 => return paths[0].to_str().map(|ref_val| ref_val.to_string()),
        _ => {}
    };

    let mut longest_path: Vec<_> = paths[0].components().collect();

    for path in &paths[1..] {
        let mut greatest_distance = 0;
        for component_pair in path.components().zip(longest_path.iter()) {
            if component_pair.0 != *component_pair.1 {
                break;
            }

            greatest_distance += 1;
        }

        if greatest_distance != longest_path.len() {
            longest_path.truncate(greatest_distance);
        }
    }

    let mut result = PathBuf::new();
    for component in longest_path {
        result.push(component.as_os_str());
    }

    result.to_str().map(|ref_val| ref_val.to_string())
}

#[cfg(test)]
#[cfg(target_family = "unix")]
mod tests {
    use std::path::{Path, PathBuf};

    use mktemp::Temp;

    use super::imp::Process;
    use super::get_longest_common_path;

    fn file_contents(path: &Path) -> String {
        use std::fs::File;
        use std::io::Read;

        let mut f = File::open(path).unwrap();
        let mut s = String::new();
        f.read_to_string(&mut s).unwrap();

        s
    }

    #[test]
    fn test_start() {
        let process = Process::new("echo hi", vec![]);

        assert!(process.is_ok());
    }

    #[test]
    fn test_wait() {
        let file = Temp::new_file().unwrap();
        let path = file.to_path_buf();
        let process = Process::new(&format!("echo hi > {}", path.to_str().unwrap()), vec![])
            .unwrap();
        process.wait();

        assert!(file_contents(&path).starts_with("hi"));
    }

    #[test]
    fn test_kill() {
        let file = Temp::new_file().unwrap();
        let path = file.to_path_buf();

        let process = Process::new(&format!("sleep 20; echo hi > {}", path.to_str().unwrap()),
                                       vec![])
            .unwrap();
        process.kill();
        process.wait();

        assert!(file_contents(&path) == "");
    }

    #[test]
    fn longest_common_path_should_return_correct_value() {
        let single_path = vec![PathBuf::from("/tmp/random/")];
        let single_result = get_longest_common_path(&single_path).unwrap();
        assert_eq!(single_result, "/tmp/random/");

        let common_paths = vec![PathBuf::from("/tmp/logs/hi"),
                                PathBuf::from("/tmp/logs/bye"),
                                PathBuf::from("/tmp/logs/bye"),
                                PathBuf::from("/tmp/logs/fly")];

        let common_result = get_longest_common_path(&common_paths).unwrap();
        assert_eq!(common_result, "/tmp/logs");

        let diverging_paths = vec![PathBuf::from("/tmp/logs/hi"), PathBuf::from("/var/logs/hi")];

        let diverging_result = get_longest_common_path(&diverging_paths).unwrap();
        assert_eq!(diverging_result, "/");

        let uneven_paths = vec![PathBuf::from("/tmp/logs/hi"),
                                PathBuf::from("/tmp/logs/"),
                                PathBuf::from("/tmp/logs/bye")];

        let uneven_result = get_longest_common_path(&uneven_paths).unwrap();
        assert_eq!(uneven_result, "/tmp/logs");
    }
}
<|endoftext|>


<commit_before>use super::rules::LRules;
use super::state::LSystem;

/// L-System processors are responsible for taking a L-System and evolving it to
// its next state.
pub trait LProcessor<S: Clone+Eq> {
    /// Try and iterate the given L-System into its next state according to
    /// its production rules.
    /// Return None if successful, Some(error_string) otherwise.
    fn iterate<'a>(lsystem: &LSystem<'a, S>) -> Result<LSystem<'a, S>, String>;
}

/// Simple thread-blocking L-System processor.
pub struct SimpleProcessor;

impl<S> LProcessor<S> for SimpleProcessor where S: Clone + Eq
{
    fn iterate<'a>(lsystem: &LSystem<'a, S>) -> Result<LSystem<'a, S>, String> {
        // allocate a new state with the worst possible size
        // (may cause overflow one or more iteration(s) earlier with huge states/production rules)
        let rules = lsystem.rules().clone();
        let new_state_size = match lsystem.state().len().checked_mul(rules.biggest_expansion()) {
            Some(v) => v,
            None => {
                return Err(format!("SimpleProcessor : usize overflow when computing new Vec size"))
            }
        };
        let mut new_state: Vec<S> = Vec::with_capacity(new_state_size);

        // iterate over the symbols
        for s in lsystem.state() {
            match rules.production(&s) {
                Some(symbols) => new_state.extend(symbols.iter().cloned()),
                None => (),
            }
        }
        new_state.shrink_to_fit();

        // return the evolved L-System
        Ok(LSystem::<S>::new(new_state, rules.clone(), Some(lsystem.iteration() + 1)))
    }
}

#[cfg(test)]
mod test {
    use rules::HashMapRules;
    use state::{LSystem, new_rules_value};
    use super::*;

    #[test]
    fn simple_processing() {
        let mut rules = HashMapRules::new(); // algae rules
        rules.set_str('A', "AB");
        rules.set_str('B', "A");
        let expected_states = ["A",
                               "AB",
                               "ABA",
                               "ABAAB",
                               "ABAABABA",
                               "ABAABABAABAAB",
                               "ABAABABAABAABABAABABA",
                               "ABAABABAABAABABAABABAABAABABAABAAB"];
        let mut lsystem = LSystem::new_with_char(&expected_states[0], new_rules_value(rules));

        for n in 0..expected_states.len() {
            assert_eq!(lsystem.iteration(), n as u64);
            let expected: Vec<char> = expected_states[n].chars().collect();
            assert_eq!(lsystem.state(), &expected[..]);
            lsystem = SimpleProcessor::iterate(&lsystem).ok().unwrap();
        }
    }
}
<commit_msg>SimpleProcessor : fixed bug<commit_after>use super::rules::LRules;
use super::state::LSystem;

/// L-System processors are responsible for taking a L-System and evolving it to
// its next state.
pub trait LProcessor<S: Clone+Eq> {
    /// Try and iterate the given L-System into its next state according to
    /// its production rules.
    /// Return None if successful, Some(error_string) otherwise.
    fn iterate<'a>(lsystem: &LSystem<'a, S>) -> Result<LSystem<'a, S>, String>;
}

/// Simple thread-blocking L-System processor.
pub struct SimpleProcessor;

impl<S> LProcessor<S> for SimpleProcessor where S: Clone + Eq
{
    fn iterate<'a>(lsystem: &LSystem<'a, S>) -> Result<LSystem<'a, S>, String> {
        // allocate a new state with the worst possible size
        // (may cause overflow one or more iteration(s) earlier with huge states/production rules)
        let rules = lsystem.rules().clone();
        let new_state_size = match lsystem.state().len().checked_mul(rules.biggest_expansion()) {
            Some(v) => v,
            None => {
                return Err(format!("SimpleProcessor : usize overflow when computing new Vec size"))
            }
        };
        let mut new_state: Vec<S> = Vec::with_capacity(new_state_size);

        // iterate over the symbols
        for s in lsystem.state() {
            match rules.production(&s) {
                Some(symbols) => new_state.extend(symbols.iter().cloned()),
                None => new_state.push(s),
            }
        }
        new_state.shrink_to_fit();

        // return the evolved L-System
        Ok(LSystem::<S>::new(new_state, rules.clone(), Some(lsystem.iteration() + 1)))
    }
}

#[cfg(test)]
mod test {
    use rules::HashMapRules;
    use state::{LSystem, new_rules_value};
    use super::*;

    #[test]
    fn simple_processing() {
        let mut rules = HashMapRules::new(); // algae rules
        rules.set_str('A', "AB");
        rules.set_str('B', "A");
        let expected_states = ["A",
                               "AB",
                               "ABA",
                               "ABAAB",
                               "ABAABABA",
                               "ABAABABAABAAB",
                               "ABAABABAABAABABAABABA",
                               "ABAABABAABAABABAABABAABAABABAABAAB"];
        let mut lsystem = LSystem::new_with_char(&expected_states[0], new_rules_value(rules));

        for n in 0..expected_states.len() {
            assert_eq!(lsystem.iteration(), n as u64);
            let expected: Vec<char> = expected_states[n].chars().collect();
            assert_eq!(lsystem.state(), &expected[..]);
            lsystem = SimpleProcessor::iterate(&lsystem).ok().unwrap();
        }
    }
}
<|endoftext|>


<commit_before>use super::gl;
use super::gl_lib::types::*;
use super::Shader;

pub struct Program {
    gl_id: GLuint
}

impl Program {
    pub unsafe fn from_id(id: GLuint) -> Program {
        Program { gl_id: id }
    }

    pub fn attach_shader(&mut self, shader: &Shader) {
        unsafe {
            gl::AttachShader(self.gl_id, shader.gl_id());
        }
    }
}

impl Drop for Program {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteProgram(self.gl_id);
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct ProgramAttrib {
    pub gl_index: GLuint
}
<commit_msg>Add `Program.link()`<commit_after>use std::mem;
use std::ptr;
use super::gl;
use super::gl_lib::types::*;
use super::GLError;
use super::Shader;

pub struct Program {
    gl_id: GLuint
}

impl Program {
    pub unsafe fn from_id(id: GLuint) -> Program {
        Program { gl_id: id }
    }

    pub fn attach_shader(&mut self, shader: &Shader) {
        unsafe {
            gl::AttachShader(self.gl_id, shader.gl_id());
        }
    }

    pub fn link(&self) -> Result<(), GLError> {
        let success = unsafe {
            gl::LinkProgram(self.gl_id);
            let mut link_status : GLint = mem::uninitialized();
            gl::GetProgramiv(self.gl_id,
                             gl::LINK_STATUS,
                             &mut link_status as *mut GLint);

            link_status == gl::TRUE as GLint
        };

        if success {
            Ok(())
        }
        else {
            unsafe {
                let mut info_length : GLint = mem::uninitialized();
                gl::GetProgramiv(self.gl_id,
                                 gl::INFO_LOG_LENGTH,
                                 &mut info_length as *mut GLint);

                let mut bytes = Vec::<u8>::with_capacity(info_length as usize);

                gl::GetProgramInfoLog(self.gl_id,
                                      info_length,
                                      ptr::null_mut(),
                                      bytes.as_mut_ptr() as *mut GLchar);
                bytes.set_len((info_length - 1) as usize);

                let msg = String::from_utf8(bytes)
                                 .unwrap_or(String::from("<Unknown error>"));

                Err(GLError { message: msg })
            }
        }
    }
}

impl Drop for Program {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteProgram(self.gl_id);
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct ProgramAttrib {
    pub gl_index: GLuint
}
<|endoftext|>