<commit_before>// See LICENSE file for copyright and license details.

#![feature(old_io, old_path)]

extern crate gl_generator;
extern crate khronos_api;

#[cfg(target_os = "windows")]
const GENERATOR: gl_generator::StructGenerator = gl_generator::StructGenerator;

#[cfg(not(target_os = "windows"))]
const GENERATOR: gl_generator::StaticStructGenerator = gl_generator::StaticStructGenerator;

fn main() {
    let dest = Path::new(std::env::var("OUT_DIR").unwrap());
    let mut file = std::fs::File::create(&dest.join("gl_bindings.rs")).unwrap();
    gl_generator::generate_bindings(
        GENERATOR,
        gl_generator::registry::Ns::Gles2,
        gl_generator::Fallbacks::None,
        khronos_api::GL_XML,
        vec![],
        "2.0",
        "core",
        &mut file,
    ).unwrap();
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>zoc_gl/build.rs: Removed 'old_io' feature<commit_after>// See LICENSE file for copyright and license details.

#![feature(old_path)]

extern crate gl_generator;
extern crate khronos_api;

#[cfg(target_os = "windows")]
const GENERATOR: gl_generator::StructGenerator = gl_generator::StructGenerator;

#[cfg(not(target_os = "windows"))]
const GENERATOR: gl_generator::StaticStructGenerator = gl_generator::StaticStructGenerator;

fn main() {
    let dest = Path::new(std::env::var("OUT_DIR").unwrap());
    let mut file = std::fs::File::create(&dest.join("gl_bindings.rs")).unwrap();
    gl_generator::generate_bindings(
        GENERATOR,
        gl_generator::registry::Ns::Gles2,
        gl_generator::Fallbacks::None,
        khronos_api::GL_XML,
        vec![],
        "2.0",
        "core",
        &mut file,
    ).unwrap();
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::str::FromStr;
use std::thread;

fn main() {

    let mat_path = Path::new("big_matrix_1.txt");

    let mat_file = File::open(&mat_path).unwrap();

    let mat_reader = BufReader::new(mat_file);

    let mut mat_line_iterator = mat_reader.lines();

    let mut mat_content: Vec<Vec<u32>> = Vec::new();

    loop {
        match mat_line_iterator.next() {
            Some(result) => {
                                let mat_line = result.unwrap();
                                let slice_iter = mat_line.as_slice().trim_matches(',').split(',')
                                    .map(|x| {
                                                FromStr::from_str(x).unwrap()
                                            });
                                mat_content.push(slice_iter.collect());
                            },

            None => break,
        }
    }
}
<commit_msg>Getting ready to multiply matrices.<commit_after>use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::str::FromStr;
use std::thread;

fn load_matrix(file_path: &Path) -> Vec<Vec<u32>> {

    let mat_file = File::open(file_path).unwrap();

    let mat_reader = BufReader::new(mat_file);

    let mut mat_line_iterator = mat_reader.lines();

    let mut mat_content: Vec<Vec<u32>> = Vec::new();

    loop {
        match mat_line_iterator.next() {
            Some(result) => {
                                let mat_line = result.unwrap();
                                let slice_iter = mat_line.as_slice().trim_matches(',').split(',')
                                    .map(|x| {
                                                FromStr::from_str(x).unwrap()
                                            });
                                mat_content.push(slice_iter.collect());
                            },

            None => break,
        }
    }

    mat_content
}

fn main() {

    let matrix_1: Vec<Vec<u32>> = load_matrix(Path::new("big_matrix_1.txt"));
    let matrix_2: Vec<Vec<u32>> = load_matrix(Path::new("big_matrix_2.txt"));

    println!("{}", matrix_1[3][10]);
    println!("{}", matrix_2[72][0]);

}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

use toml::Value;

use error::RefErrorKind as REK;
use result::Result;

#[derive(Default)]
pub struct RefFlags {
    content_hashing:       bool,
    permission_tracking:   bool,
}

impl RefFlags {

    /// Read the RefFlags from a TOML document
    ///
    /// Assumes that the whole TOML tree is passed. So this looks up `ref.flags` to get the flags.
    /// It assumes that this is a Map with Key = <name of the setting> and Value = boolean.
    pub fn read(v: &Value) -> Result<RefFlags> {
        fn get_field(v: &Value, key: &str) -> Result<bool> {
            match v.lookup(key) {
                Some(&Value::Boolean(b)) => Ok(b),
                Some(_) => Err(REK::HeaderTypeError.into()),
                None    => Err(REK::HeaderFieldMissingError.into()),
            }
        }

        Ok(RefFlags {
            content_hashing:     try!(get_field(v, "ref.flags.content_hashing")),
            permission_tracking: try!(get_field(v, "ref.flags.permission_tracking")),
        })
    }

    /// Alias for `RefFlags::content_hashing()`
    pub fn is_often_moving(mut self, b: bool) -> RefFlags {
        self.with_content_hashing(b)
    }

    pub fn with_content_hashing(mut self, b: bool) -> RefFlags {
        self.content_hashing = b;
        self
    }

    pub fn with_permission_tracking(mut self, b: bool) -> RefFlags {
        self.permission_tracking = b;
        self
    }

    pub fn get_content_hashing(&self) -> bool {
        self.content_hashing
    }

    pub fn get_permission_tracking(&self) -> bool {
        unimplemented!()
    }

}

impl Into<Value> for RefFlags {

    /// Build a TOML::Value from this RefFlags object.
    ///
    /// Returns a Map which should be set in `ref.flags` in the header.
    fn into(self) -> Value {
        let mut btm = BTreeMap::new();
        btm.insert(String::from("content_hashing"),     Value::Boolean(self.content_hashing));
        btm.insert(String::from("permission_tracking"), Value::Boolean(self.permission_tracking));
        return Value::Table(btm)
    }

}

<commit_msg>Impl RefFlags::get_permission_tracking()<commit_after>use std::collections::BTreeMap;

use toml::Value;

use error::RefErrorKind as REK;
use result::Result;

#[derive(Default)]
pub struct RefFlags {
    content_hashing:       bool,
    permission_tracking:   bool,
}

impl RefFlags {

    /// Read the RefFlags from a TOML document
    ///
    /// Assumes that the whole TOML tree is passed. So this looks up `ref.flags` to get the flags.
    /// It assumes that this is a Map with Key = <name of the setting> and Value = boolean.
    pub fn read(v: &Value) -> Result<RefFlags> {
        fn get_field(v: &Value, key: &str) -> Result<bool> {
            match v.lookup(key) {
                Some(&Value::Boolean(b)) => Ok(b),
                Some(_) => Err(REK::HeaderTypeError.into()),
                None    => Err(REK::HeaderFieldMissingError.into()),
            }
        }

        Ok(RefFlags {
            content_hashing:     try!(get_field(v, "ref.flags.content_hashing")),
            permission_tracking: try!(get_field(v, "ref.flags.permission_tracking")),
        })
    }

    /// Alias for `RefFlags::content_hashing()`
    pub fn is_often_moving(mut self, b: bool) -> RefFlags {
        self.with_content_hashing(b)
    }

    pub fn with_content_hashing(mut self, b: bool) -> RefFlags {
        self.content_hashing = b;
        self
    }

    pub fn with_permission_tracking(mut self, b: bool) -> RefFlags {
        self.permission_tracking = b;
        self
    }

    pub fn get_content_hashing(&self) -> bool {
        self.content_hashing
    }

    pub fn get_permission_tracking(&self) -> bool {
        self.permission_tracking
    }

}

impl Into<Value> for RefFlags {

    /// Build a TOML::Value from this RefFlags object.
    ///
    /// Returns a Map which should be set in `ref.flags` in the header.
    fn into(self) -> Value {
        let mut btm = BTreeMap::new();
        btm.insert(String::from("content_hashing"),     Value::Boolean(self.content_hashing));
        btm.insert(String::from("permission_tracking"), Value::Boolean(self.permission_tracking));
        return Value::Table(btm)
    }

}

<|endoftext|>


<commit_before>use std::collections::BTreeMap;

use toml::Value;

use error::RefErrorKind as REK;
use result::Result;

#[derive(Default)]
pub struct RefFlags {
    content_hashing:       bool,
    permission_tracking:   bool,
}

impl RefFlags {

    /// Read the RefFlags from a TOML document
    ///
    /// Assumes that the whole TOML tree is passed. So this looks up `ref.flags` to get the flags.
    /// It assumes that this is a Map with Key = <name of the setting> and Value = boolean.
    pub fn read(v: &Value) -> Result<RefFlags> {
        fn get_field(v: &Value, key: &str) -> Result<bool> {
            match v.lookup(key) {
                Some(&Value::Boolean(b)) => Ok(b),
                Some(_) => Err(REK::HeaderTypeError.into()),
                None    => Err(REK::HeaderFieldMissingError.into()),
            }
        }

        Ok(RefFlags {
            content_hashing:     try!(get_field(v, "ref.flags.content_hashing")),
            permission_tracking: try!(get_field(v, "ref.flags.permission_tracking")),
        })
    }

    /// Build a TOML::Value from this RefFlags object.
    ///
    /// Returns a Map which should be set in `ref.flags` in the header.
    pub fn into_toml(self) -> Result<Value> {
        unimplemented!()
    }

    /// Alias for `RefFlags::content_hashing()`
    pub fn is_often_moving(mut self, b: bool) -> RefFlags {
        self.with_content_hashing(b)
    }

    pub fn with_content_hashing(self, b: bool) -> RefFlags {
        unimplemented!()
    }

    pub fn with_permission_tracking(mut self, b: bool) -> RefFlags {
        self.permission_tracking = b;
        self
    }

    pub fn get_content_hashing(&self) -> bool {
        unimplemented!()
    }

    pub fn get_permission_tracking(&self) -> bool {
        unimplemented!()
    }

}

<commit_msg>Impl RefFlags::into_toml() as Into<Value> for RefFlags<commit_after>use std::collections::BTreeMap;

use toml::Value;

use error::RefErrorKind as REK;
use result::Result;

#[derive(Default)]
pub struct RefFlags {
    content_hashing:       bool,
    permission_tracking:   bool,
}

impl RefFlags {

    /// Read the RefFlags from a TOML document
    ///
    /// Assumes that the whole TOML tree is passed. So this looks up `ref.flags` to get the flags.
    /// It assumes that this is a Map with Key = <name of the setting> and Value = boolean.
    pub fn read(v: &Value) -> Result<RefFlags> {
        fn get_field(v: &Value, key: &str) -> Result<bool> {
            match v.lookup(key) {
                Some(&Value::Boolean(b)) => Ok(b),
                Some(_) => Err(REK::HeaderTypeError.into()),
                None    => Err(REK::HeaderFieldMissingError.into()),
            }
        }

        Ok(RefFlags {
            content_hashing:     try!(get_field(v, "ref.flags.content_hashing")),
            permission_tracking: try!(get_field(v, "ref.flags.permission_tracking")),
        })
    }

    /// Alias for `RefFlags::content_hashing()`
    pub fn is_often_moving(mut self, b: bool) -> RefFlags {
        self.with_content_hashing(b)
    }

    pub fn with_content_hashing(self, b: bool) -> RefFlags {
        unimplemented!()
    }

    pub fn with_permission_tracking(mut self, b: bool) -> RefFlags {
        self.permission_tracking = b;
        self
    }

    pub fn get_content_hashing(&self) -> bool {
        unimplemented!()
    }

    pub fn get_permission_tracking(&self) -> bool {
        unimplemented!()
    }

}

impl Into<Value> for RefFlags {

    /// Build a TOML::Value from this RefFlags object.
    ///
    /// Returns a Map which should be set in `ref.flags` in the header.
    fn into(self) -> Value {
        let mut btm = BTreeMap::new();
        btm.insert(String::from("content_hashing"),     Value::Boolean(self.content_hashing));
        btm.insert(String::from("permission_tracking"), Value::Boolean(self.permission_tracking));
        return Value::Table(btm)
    }

}

<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::io::Write;
use std::io::stderr;

use log::{Log, LogLevel, LogRecord, LogMetadata};

use ansi_term::Style;
use ansi_term::Colour;
use ansi_term::ANSIString;

pub struct ImagLogger {
    prefix: String,
    lvl: LogLevel,
    color_enabled: bool,
}

impl ImagLogger {

    pub fn new(lvl: LogLevel) -> ImagLogger {
        ImagLogger {
            prefix: "[imag]".to_owned(),
            lvl: lvl,
            color_enabled: true
        }
    }

    pub fn with_prefix(mut self, pref: String) -> ImagLogger {
        self.prefix = pref;
        self
    }

    pub fn with_color(mut self, b: bool) -> ImagLogger {
        self.color_enabled = b;
        self
    }

    fn style_or_not(&self, c: Style, s: String) -> ANSIString {
        if self.color_enabled {
            c.paint(s)
        } else {
            ANSIString::from(s)
        }
    }

    fn color_or_not(&self, c: Colour, s: String) -> ANSIString {
        if self.color_enabled {
            c.paint(s)
        } else {
            ANSIString::from(s)
        }
    }

}

impl Log for ImagLogger {

    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.lvl
    }

    fn log(&self, record: &LogRecord) {
        use ansi_term::Colour::Red;
        use ansi_term::Colour::Yellow;
        use ansi_term::Colour::Cyan;

        if self.enabled(record.metadata()) {
            // TODO: This is just simple logging. Maybe we can enhance this lateron
            let loc = record.location();
            match record.metadata().level() {
                LogLevel::Debug => {
                    let lvl  = self.color_or_not(Cyan, format!("{}", record.level()));
                    let file = self.color_or_not(Cyan, format!("{}", loc.file()));
                    let ln   = self.color_or_not(Cyan, format!("{}", loc.line()));
                    let args = self.color_or_not(Cyan, format!("{}", record.args()));

                    writeln!(stderr(), "{}[{: <5}][{}][{: >5}]: {}", self.prefix, lvl, file, ln, args).ok();
                },
                LogLevel::Warn | LogLevel::Error => {
                    let lvl  = self.style_or_not(Red.blink(), format!("{}", record.level()));
                    let args = self.color_or_not(Red, format!("{}", record.args()));

                    writeln!(stderr(), "{}[{: <5}]: {}", self.prefix, lvl, args).ok();
                },
                LogLevel::Info => {
                    let lvl  = self.color_or_not(Yellow, format!("{}", record.level()));
                    let args = self.color_or_not(Yellow, format!("{}", record.args()));

                    writeln!(stderr(), "{}[{: <5}]: {}", self.prefix, lvl, args).ok();
                },
                _ => {
                    writeln!(stderr(), "{}[{: <5}]: {}", self.prefix, record.level(), record.args()).ok();
                },
            }
        }
    }
}

<commit_msg>ImagLogger: Add option to not include file/line in dbg logging<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::io::Write;
use std::io::stderr;

use log::{Log, LogLevel, LogRecord, LogMetadata};

use ansi_term::Style;
use ansi_term::Colour;
use ansi_term::ANSIString;

pub struct ImagLogger {
    prefix: String,
    dbg_fileline: bool,
    lvl: LogLevel,
    color_enabled: bool,
}

impl ImagLogger {

    pub fn new(lvl: LogLevel) -> ImagLogger {
        ImagLogger {
            prefix: "[imag]".to_owned(),
            dbg_fileline: true,
            lvl: lvl,
            color_enabled: true
        }
    }

    pub fn with_dbg_file_and_line(mut self, b: bool) -> ImagLogger {
        self.dbg_fileline = b;
        self
    }

    pub fn with_prefix(mut self, pref: String) -> ImagLogger {
        self.prefix = pref;
        self
    }

    pub fn with_color(mut self, b: bool) -> ImagLogger {
        self.color_enabled = b;
        self
    }

    fn style_or_not(&self, c: Style, s: String) -> ANSIString {
        if self.color_enabled {
            c.paint(s)
        } else {
            ANSIString::from(s)
        }
    }

    fn color_or_not(&self, c: Colour, s: String) -> ANSIString {
        if self.color_enabled {
            c.paint(s)
        } else {
            ANSIString::from(s)
        }
    }

}

impl Log for ImagLogger {

    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.lvl
    }

    fn log(&self, record: &LogRecord) {
        use ansi_term::Colour::Red;
        use ansi_term::Colour::Yellow;
        use ansi_term::Colour::Cyan;

        if self.enabled(record.metadata()) {
            // TODO: This is just simple logging. Maybe we can enhance this lateron
            let loc = record.location();
            match record.metadata().level() {
                LogLevel::Debug => {
                    let lvl  = self.color_or_not(Cyan, format!("{}", record.level()));
                    let args = self.color_or_not(Cyan, format!("{}", record.args()));
                    if self.dbg_fileline {
                        let file = self.color_or_not(Cyan, format!("{}", loc.file()));
                        let ln   = self.color_or_not(Cyan, format!("{}", loc.line()));

                        writeln!(stderr(), "{}[{: <5}][{}][{: >5}]: {}", self.prefix, lvl, file, ln, args).ok();
                    } else {
                        writeln!(stderr(), "{}[{: <5}]: {}", self.prefix, lvl, args).ok();
                    }
                },
                LogLevel::Warn | LogLevel::Error => {
                    let lvl  = self.style_or_not(Red.blink(), format!("{}", record.level()));
                    let args = self.color_or_not(Red, format!("{}", record.args()));

                    writeln!(stderr(), "{}[{: <5}]: {}", self.prefix, lvl, args).ok();
                },
                LogLevel::Info => {
                    let lvl  = self.color_or_not(Yellow, format!("{}", record.level()));
                    let args = self.color_or_not(Yellow, format!("{}", record.args()));

                    writeln!(stderr(), "{}[{: <5}]: {}", self.prefix, lvl, args).ok();
                },
                _ => {
                    writeln!(stderr(), "{}[{: <5}]: {}", self.prefix, record.level(), record.args()).ok();
                },
            }
        }
    }
}

<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::process::Command;
use std::env;

fn main() {
    let target = env::var("TARGET").unwrap();
    // let out_dir = env::var("OUT_DIR").unwrap();
    let current_dir = env::current_dir().unwrap();

    // println!("target:      {:?}", target);
    // println!("out_dir:     {:?}", out_dir);
    // println!("current_dir: {:?}", current_dir);

    let libqmlbind_dir = current_dir.join("libqmlbind");
    let libqmlbind_build_dir = libqmlbind_dir.join("build");

    std::fs::create_dir_all(&libqmlbind_build_dir).unwrap();

    // Initialize git submodule
    if !libqmlbind_dir.join(".git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    let output = Command::new("qmake").arg("../qmlbind")
                                      .current_dir(&libqmlbind_build_dir)
                                      .output().unwrap();
    println!("output.status: {}", output.status);
    println!("output.stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("output.stderr: {}", String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success(), "failed to execute qmake process");

    let output = Command::new("make").current_dir(&libqmlbind_build_dir).output().unwrap();
    println!("output.status: {}", output.status);
    println!("output.stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("output.stderr: {}", String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success(), "failed to execute make process");

    let output = Command::new("make").arg("staticlib")
                                     .current_dir(&libqmlbind_build_dir)
                                     .output().unwrap();
    println!("output.status: {}", output.status);
    println!("output.stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("output.stderr: {}", String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success(), "failed to execute 'make staticlib' process");

    println!("cargo:rustc-link-search={}", libqmlbind_build_dir.to_str().unwrap());
    println!("cargo:rustc-link-lib=static=qmlbind");

    let qt_dir = env::var("QT_DIR").map(|p| PathBuf::from(p)).unwrap_or({
        println!("Environnement variable 'QT_DIR' not set!");
        println!("Defaulting to ${{HOME}}/Qt/${{QT_VER}}/${{QT_COMP}} where:");
        let home_dir = env::home_dir().map(|p| PathBuf::from(p)).unwrap();
        let default_qt_ver = "5.7".to_string();
        let default_qt_comp = if target.contains("linux") {
            "gcc_64".to_string()
        } else if target.contains("darwin") {
            "clang_64".to_string()
        } else {
            panic!("Unsuported platform in gallery's build.rs!")
        };
        println!("    QT_VER:  {}", default_qt_ver);
        println!("    QT_COMP: {}", default_qt_comp);
        let qt_dir_default = home_dir.join("Qt")
                                  .join(env::var("QT_VER").unwrap_or(default_qt_ver))
                                  .join(env::var("QT_COMP").unwrap_or(default_qt_comp));
        qt_dir_default
    });
    println!("Using Qt directory: {:?}", qt_dir);
    println!("Use QT_DIR environment variable to ovewrite.");

    let qt_lib_dir = qt_dir.join("lib").to_str().unwrap().to_string();

    let osx_framework = if target.contains("darwin") { "=framework" }
                        else  { "" };
    // On Linux, libraries are name "Qt5Core", not "QtCore" as on OSX
    let linux_qt_lib_ver = if target.contains("linux") { "5" }
                           else  { "" };

    println!("cargo:rustc-link-search{}={}", osx_framework, qt_lib_dir);

    println!("cargo:rustc-link-lib{}=Qt{}Core", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Network", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Gui", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Qml", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Widgets", osx_framework, linux_qt_lib_ver);

    // On Linux, Qt needs icui18n, icuuc and icudata
    if target.contains("linux") {
        println!("cargo:rustc-link-lib=icui18n");
        println!("cargo:rustc-link-lib=icuuc");
        println!("cargo:rustc-link-lib=icudata");
    }

    println!("cargo:rustc-flags=-l stdc++");
}
<commit_msg>libqmlbind-sys: Convert as many unwrap() in build script to unwrap_or_else()<commit_after>use std::path::PathBuf;
use std::process::Command;
use std::env;

fn main() {
    let target = env::var("TARGET").expect("Environnement variable TARGET not set");
    // let out_dir = env::var("OUT_DIR").expect("Failed to get output directory");
    let current_dir = env::current_dir().expect("Failed to get current directory");

    // println!("target:      {:?}", target);
    // println!("out_dir:     {:?}", out_dir);
    // println!("current_dir: {:?}", current_dir);

    let libqmlbind_dir = current_dir.join("libqmlbind");
    let libqmlbind_build_dir = libqmlbind_dir.join("build");

    std::fs::create_dir_all(&libqmlbind_build_dir).unwrap_or_else(|e| panic!("Failed to create libqmlbind build directory: {}", e));

    // Initialize git submodule
    if !libqmlbind_dir.join(".git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status()
                                   .unwrap_or_else(|e| panic!("Failed to initialize git submodule: {}", e));
    }

    let output = Command::new("qmake").arg("../qmlbind")
                                      .current_dir(&libqmlbind_build_dir)
                                      .output()
                                      .unwrap_or_else(|e| panic!("Failed execute qmake: {}", e));
    println!("output.status: {}", output.status);
    println!("output.stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("output.stderr: {}", String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success(), "failed to execute qmake process");

    let output = Command::new("make")
                                .current_dir(&libqmlbind_build_dir)
                                .output()
                                .unwrap_or_else(|e| panic!("Failed execute make : {}", e));
    println!("output.status: {}", output.status);
    println!("output.stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("output.stderr: {}", String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success(), "failed to execute make process");

    let output = Command::new("make").arg("staticlib")
                                     .current_dir(&libqmlbind_build_dir)
                                     .output()
                                     .unwrap_or_else(|e| panic!("Failed execute 'make staticlib': {}", e));
    println!("output.status: {}", output.status);
    println!("output.stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("output.stderr: {}", String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success(), "failed to execute 'make staticlib' process");

    println!("cargo:rustc-link-search={}", libqmlbind_build_dir.to_str().unwrap());
    println!("cargo:rustc-link-lib=static=qmlbind");

    let qt_dir = env::var("QT_DIR").map(|p| PathBuf::from(p)).unwrap_or({
        println!("Environnement variable 'QT_DIR' not set!");
        println!("Defaulting to ${{HOME}}/Qt/${{QT_VER}}/${{QT_COMP}} where:");
        let home_dir = env::home_dir().map(|p| PathBuf::from(p)).unwrap();
        let default_qt_ver = "5.7".to_string();
        let default_qt_comp = if target.contains("linux") {
            "gcc_64".to_string()
        } else if target.contains("darwin") {
            "clang_64".to_string()
        } else {
            panic!("Unsuported platform in gallery's build.rs!")
        };
        println!("    QT_VER:  {}", default_qt_ver);
        println!("    QT_COMP: {}", default_qt_comp);
        let qt_dir_default = home_dir.join("Qt")
                                  .join(env::var("QT_VER").unwrap_or(default_qt_ver))
                                  .join(env::var("QT_COMP").unwrap_or(default_qt_comp));
        qt_dir_default
    });
    println!("Using Qt directory: {:?}", qt_dir);
    println!("Use QT_DIR environment variable to ovewrite.");

    let qt_lib_dir = qt_dir.join("lib").to_str().unwrap().to_string();

    let osx_framework = if target.contains("darwin") { "=framework" }
                        else  { "" };
    // On Linux, libraries are name "Qt5Core", not "QtCore" as on OSX
    let linux_qt_lib_ver = if target.contains("linux") { "5" }
                           else  { "" };

    println!("cargo:rustc-link-search{}={}", osx_framework, qt_lib_dir);

    println!("cargo:rustc-link-lib{}=Qt{}Core", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Network", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Gui", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Qml", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Widgets", osx_framework, linux_qt_lib_ver);

    // On Linux, Qt needs icui18n, icuuc and icudata
    if target.contains("linux") {
        println!("cargo:rustc-link-lib=icui18n");
        println!("cargo:rustc-link-lib=icuuc");
        println!("cargo:rustc-link-lib=icudata");
    }

    println!("cargo:rustc-flags=-l stdc++");
}
<|endoftext|>


<commit_before>use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::env;

fn main() {
    let target = env::var("TARGET").unwrap();

    // Initialize git submodule
    if !Path::new("libqmlbind/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    Command::new("qmake").current_dir("libqmlbind").output().unwrap();
    Command::new("make").current_dir("libqmlbind").output().unwrap();
    Command::new("make").arg("staticlib").current_dir("libqmlbind/qmlbind").output().unwrap();

    println!("cargo:rustc-flags=-L libqmlbind/qmlbind");
    println!("cargo:rustc-link-lib=static=qmlbind");
    // println!("cargo:rustc-link-lib=qmlbind");

    let qt_dir = env::var("QT_DIR").map(|p| PathBuf::from(p)).unwrap_or({
        println!("Environnement variable 'QT_DIR' not set!");
        println!("Defaulting to ${{HOME}}/Qt/${{QT_VER}}/${{QT_COMP}} where:");
        let home_dir = env::home_dir().map(|p| PathBuf::from(p)).unwrap();
        let default_qt_ver = "5.7".to_string();
        let default_qt_comp = if target.contains("linux") {
            "gcc_64".to_string()
        } else if target.contains("darwin") {
            "clang_64".to_string()
        } else {
            panic!("Unsuported platform in gallery's build.rs!")
        };
        println!("    QT_VER:  {}", default_qt_ver);
        println!("    QT_COMP: {}", default_qt_comp);
        let qt_dir_default = home_dir.join("Qt")
                                  .join(env::var("QT_VER").unwrap_or(default_qt_ver))
                                  .join(env::var("QT_COMP").unwrap_or(default_qt_comp));
        qt_dir_default
    });
    println!("Using Qt directory: {:?}", qt_dir);
    println!("Use QT_DIR environment variable to ovewrite.");

    let qt_lib_dir = qt_dir.join("lib").to_str().unwrap().to_string();

    let osx_framework = if target.contains("darwin") { "=framework" }
                        else  { "" };
    // On Linux, libraries are name "Qt5Core", not "QtCore" as on OSX
    let linux_qt_lib_ver = if target.contains("linux") { "5" }
                           else  { "" };

    println!("cargo:rustc-link-search{}={}", osx_framework, qt_lib_dir);

    println!("cargo:rustc-link-lib{}=Qt{}Core", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Network", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Gui", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Qml", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Widgets", osx_framework, linux_qt_lib_ver);

    println!("cargo:rustc-flags=-l stdc++");
}
<commit_msg>libqmlbind-sys: On linux, link against icui18n, icuuc and icudata too<commit_after>use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::env;

fn main() {
    let target = env::var("TARGET").unwrap();

    // Initialize git submodule
    if !Path::new("libqmlbind/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    Command::new("qmake").current_dir("libqmlbind").output().unwrap();
    Command::new("make").current_dir("libqmlbind").output().unwrap();
    Command::new("make").arg("staticlib").current_dir("libqmlbind/qmlbind").output().unwrap();

    println!("cargo:rustc-flags=-L libqmlbind/qmlbind");
    println!("cargo:rustc-link-lib=static=qmlbind");
    // println!("cargo:rustc-link-lib=qmlbind");

    let qt_dir = env::var("QT_DIR").map(|p| PathBuf::from(p)).unwrap_or({
        println!("Environnement variable 'QT_DIR' not set!");
        println!("Defaulting to ${{HOME}}/Qt/${{QT_VER}}/${{QT_COMP}} where:");
        let home_dir = env::home_dir().map(|p| PathBuf::from(p)).unwrap();
        let default_qt_ver = "5.7".to_string();
        let default_qt_comp = if target.contains("linux") {
            "gcc_64".to_string()
        } else if target.contains("darwin") {
            "clang_64".to_string()
        } else {
            panic!("Unsuported platform in gallery's build.rs!")
        };
        println!("    QT_VER:  {}", default_qt_ver);
        println!("    QT_COMP: {}", default_qt_comp);
        let qt_dir_default = home_dir.join("Qt")
                                  .join(env::var("QT_VER").unwrap_or(default_qt_ver))
                                  .join(env::var("QT_COMP").unwrap_or(default_qt_comp));
        qt_dir_default
    });
    println!("Using Qt directory: {:?}", qt_dir);
    println!("Use QT_DIR environment variable to ovewrite.");

    let qt_lib_dir = qt_dir.join("lib").to_str().unwrap().to_string();

    let osx_framework = if target.contains("darwin") { "=framework" }
                        else  { "" };
    // On Linux, libraries are name "Qt5Core", not "QtCore" as on OSX
    let linux_qt_lib_ver = if target.contains("linux") { "5" }
                           else  { "" };

    println!("cargo:rustc-link-search{}={}", osx_framework, qt_lib_dir);

    println!("cargo:rustc-link-lib{}=Qt{}Core", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Network", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Gui", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Qml", osx_framework, linux_qt_lib_ver);
    println!("cargo:rustc-link-lib{}=Qt{}Widgets", osx_framework, linux_qt_lib_ver);

    // On Linux, Qt needs icui18n, icuuc and icudata
    if target.contains("linux") {
        println!("cargo:rustc-link-lib=icui18n");
        println!("cargo:rustc-link-lib=icuuc");
        println!("cargo:rustc-link-lib=icudata");
    }

    println!("cargo:rustc-flags=-l stdc++");
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate walkdir;
extern crate syntax;

use std;
use std::env;
use std::process::Command;

use self::walkdir::DirEntry;

macro_rules! errorf {
    ($($tt:tt)*) => {
        {
            use ::std::io::Write;
            let stderr = ::std::io::stderr();
            write!(stderr.lock(), $($tt)*).unwrap();
        }
    };
}

pub mod parse;
pub mod respan;

pub fn check_min_stack() {
    let min_stack_value = env::var("RUST_MIN_STACK")
        .expect("RUST_MIN_STACK env var should be set since some tests require it.");
    let min_stack_value: usize = min_stack_value.parse()
        .expect("RUST_MIN_STACK env var should be set since some tests require it.");
    assert!(min_stack_value >= 16000000);
}

/// Read the `ABORT_AFTER_FAILURE` environment variable, and parse it.
pub fn abort_after() -> usize {
    match env::var("ABORT_AFTER_FAILURE") {
        Ok(s) => s.parse().expect("failed to parse ABORT_AFTER_FAILURE"),
        Err(_) => std::usize::MAX,
    }
}

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }
    let path_string = path.to_string_lossy();
    let path_string = if cfg!(windows) {
        path_string.replace('\\', "/").into()
    } else {
        path_string
    };
    // TODO assert that parsing fails on the parse-fail cases
    if path_string.starts_with("tests/rust/src/test/parse-fail") ||
       path_string.starts_with("tests/rust/src/test/compile-fail") {
        return false;
    }

    if path_string.starts_with("tests/rust/src/test/ui") {
        let stderr_path = path.with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    // TODO: support `macro` definitions
    if path_string.starts_with("tests/rust/src/test/run-pass/hygiene") {
        return false;
    }

    match path_string.as_ref() {
        // TODO better support for attributes
        //
        //      let a = A { #[a] b: c };
        "tests/rust/src/librustc_data_structures/blake2b.rs" |
        // TODO better support for attributes
        //
        //      enum A { B = #[a] 2 }
        "tests/rust/src/test/incremental/hashes/enum_defs.rs" |
        // TODO better support for attributes
        //
        //      { #![foo] }
        "tests/rust/src/test/pretty/stmt_expr_attributes.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/cfg_stmt_expr.rs" |
        // TODO weird glob import
        //
        //      use ::*;
        "tests/rust/src/test/run-pass/import-glob-crate.rs" |
        // TODO better support for attributes
        //
        //      impl Foo { #![a] }
        "tests/rust/src/test/run-pass/inner-attrs-on-impl.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/item-attributes.rs" |
        // TODO support lifetimes before traits
        //
        //      Box<'foo + Bar>
        "tests/rust/src/test/run-pass/trait-object-lifetime-first.rs" |
        // TODO feature(crate_in_paths)
        //
        //      use crate as root;
        //      pub(in crate::m) struct S;
        //      ::crate::f();
        "tests/rust/src/test/run-pass/rfc-2126-crate-paths/crate-path-absolute.rs" |
        // TODO feature(use_nested_groups)
        //
        //      use a::{B, D::{self, *, g::H}};
        "tests/rust/src/test/run-pass/use-nested-groups.rs" |
        // TODO where-clause with parens
        //
        //      where U: (FnOnce(T) -> V) + 'static
        "tests/rust/src/test/ui/e0119/auxiliary/complex_impl_support.rs" |
        // not actually a test case
        "tests/rust/src/test/run-pass/auxiliary/macro-include-items-expr.rs" => false,
        _ => true,
    }
}

pub fn clone_rust() {
    let result = Command::new("tests/rust/clone.sh").status().unwrap();
    println!("result: {}", result);
    assert!(result.success());
}
<commit_msg>2.0 macro definitions no longer need to be excluded<commit_after>#![allow(dead_code)]

extern crate walkdir;
extern crate syntax;

use std;
use std::env;
use std::process::Command;

use self::walkdir::DirEntry;

macro_rules! errorf {
    ($($tt:tt)*) => {
        {
            use ::std::io::Write;
            let stderr = ::std::io::stderr();
            write!(stderr.lock(), $($tt)*).unwrap();
        }
    };
}

pub mod parse;
pub mod respan;

pub fn check_min_stack() {
    let min_stack_value = env::var("RUST_MIN_STACK")
        .expect("RUST_MIN_STACK env var should be set since some tests require it.");
    let min_stack_value: usize = min_stack_value.parse()
        .expect("RUST_MIN_STACK env var should be set since some tests require it.");
    assert!(min_stack_value >= 16000000);
}

/// Read the `ABORT_AFTER_FAILURE` environment variable, and parse it.
pub fn abort_after() -> usize {
    match env::var("ABORT_AFTER_FAILURE") {
        Ok(s) => s.parse().expect("failed to parse ABORT_AFTER_FAILURE"),
        Err(_) => std::usize::MAX,
    }
}

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }
    let path_string = path.to_string_lossy();
    let path_string = if cfg!(windows) {
        path_string.replace('\\', "/").into()
    } else {
        path_string
    };
    // TODO assert that parsing fails on the parse-fail cases
    if path_string.starts_with("tests/rust/src/test/parse-fail") ||
       path_string.starts_with("tests/rust/src/test/compile-fail") {
        return false;
    }

    if path_string.starts_with("tests/rust/src/test/ui") {
        let stderr_path = path.with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    match path_string.as_ref() {
        // TODO better support for attributes
        //
        //      let a = A { #[a] b: c };
        "tests/rust/src/librustc_data_structures/blake2b.rs" |
        // TODO better support for attributes
        //
        //      enum A { B = #[a] 2 }
        "tests/rust/src/test/incremental/hashes/enum_defs.rs" |
        // TODO better support for attributes
        //
        //      { #![foo] }
        "tests/rust/src/test/pretty/stmt_expr_attributes.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/cfg_stmt_expr.rs" |
        // TODO weird glob import
        //
        //      use ::*;
        "tests/rust/src/test/run-pass/import-glob-crate.rs" |
        // TODO better support for attributes
        //
        //      impl Foo { #![a] }
        "tests/rust/src/test/run-pass/inner-attrs-on-impl.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/item-attributes.rs" |
        // TODO support lifetimes before traits
        //
        //      Box<'foo + Bar>
        "tests/rust/src/test/run-pass/trait-object-lifetime-first.rs" |
        // TODO feature(crate_in_paths)
        //
        //      use crate as root;
        //      pub(in crate::m) struct S;
        //      ::crate::f();
        "tests/rust/src/test/run-pass/rfc-2126-crate-paths/crate-path-absolute.rs" |
        // TODO feature(use_nested_groups)
        //
        //      use a::{B, D::{self, *, g::H}};
        "tests/rust/src/test/run-pass/use-nested-groups.rs" |
        // TODO where-clause with parens
        //
        //      where U: (FnOnce(T) -> V) + 'static
        "tests/rust/src/test/ui/e0119/auxiliary/complex_impl_support.rs" |
        // not actually a test case
        "tests/rust/src/test/run-pass/auxiliary/macro-include-items-expr.rs" => false,
        _ => true,
    }
}

pub fn clone_rust() {
    let result = Command::new("tests/rust/clone.sh").status().unwrap();
    println!("result: {}", result);
    assert!(result.success());
}
<|endoftext|>


<commit_before>/* Copyright 2016 Torbjørn Birch Moltu
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://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.
 */

#![feature(unicode)]// reference implementations of to_slice

//! Test that every method gives the correct result for valid values.
//! Except iterators, which are stateful.

use std::char;
use std::str::{self,FromStr};
use std::hash::{Hash,SipHasher};
extern crate encode_unicode;
use encode_unicode::*;

#[test]
fn equal_defaults() {
    assert_eq!(Utf8Char::default().to_char(), char::default());
    assert_eq!(Utf16Char::default().to_char(), char::default());
}

#[test]
fn same_size_as_char() {
    use std::mem::size_of;
    assert_eq!(size_of::<Utf8Char>(), size_of::<char>());
    assert_eq!(size_of::<Utf16Char>(), size_of::<char>());
}

const EDGES_AND_BETWEEN: [u32;13] = [
    0x0,// min
    0x3b,// between
    0x7f,// max 1-byte UTF-8
    0x80,// min 2-byte UTF-8
    0x111,// between
    0x7ff,// max 2-byte UTF-8
    0x800,// min 3-byte UTF-8
    0xd7ff,// before reserved
    0xe000,// after reserved
    0xffff,// max UTF-16 single and 3-byte UTF-8
    0x10000,// min UTF-16 surrogate and 4-byte UTF-8
    0xabcde,// between
    0x10ffff,// max
];

fn test(c: u32) {
    let c = char::from_u32(c).expect(&format!("{:x} is not a valid char", c));
    assert_eq!(char::from_u32_detailed(c as u32), Ok(c));
    let sh = &mut SipHasher::new();

    // UTF-8
    let uc = c.to_utf8();
    assert_eq!(uc.to_char(), c);
    assert_eq!(uc.hash(sh), c.hash(sh));

    let mut reference_dst = [0;4];
    let mut len = None;
    for i in 0..5 {
        let mut test_dst = [0;4];
        len = c.encode_utf8(&mut reference_dst[..i]);
        assert_eq!(c.to_utf8_slice(&mut test_dst[..i]), len);
        assert_eq!(test_dst, reference_dst);
        assert_eq!(uc.to_slice(&mut test_dst[..i]), len);
        assert_eq!(test_dst, reference_dst);
    }
    let len = len.expect(&format!("encode_utf8 never succeded: c={}={:x}, utf8={:?}", c, c as u32, reference_dst));
    let str_ = str::from_utf8(&reference_dst[..len]).unwrap();
    let ustr = Utf8Char::from_str(str_).unwrap();
    assert_eq!(ustr.to_array().0, uc.to_array().0);// bitwise equality

    assert_eq!(reference_dst[0].extra_utf8_bytes(), Ok(len-1));
    assert_eq!(reference_dst[0].extra_utf8_bytes_unchecked(), len-1);
    assert_eq!(c.to_utf8_array(),  (reference_dst, len));
    assert_eq!(char::from_utf8_array(reference_dst), Ok(c));
    assert_eq!(char::from_utf8_slice(&reference_dst[..len]), Ok((c,len)));
    for other in &EDGES_AND_BETWEEN {
        let other = unsafe{ char::from_u32_unchecked(*other) };
        let uother = other.to_utf8();
        assert_eq!(uc == uother,  c == other);
        assert_eq!(uc.hash(sh)==other.hash(sh),  c.hash(sh)==uother.hash(sh));
        assert_eq!(uc.cmp(&uother), c.cmp(&other));
    }
    assert_eq!(uc.to_array(),  (reference_dst, len));
    assert_eq!(Utf8Char::from_array(reference_dst), Ok(uc));
    assert_eq!(Utf8Char::from_slice_start(&reference_dst[..len]), Ok((uc,len)));
    assert_eq!(c.iter_utf8_bytes().len(), len);
    let iterated: Vec<_> = c.iter_utf8_bytes().collect();
    assert_eq!(iterated[..], reference_dst[..len]);
    assert_eq!(<AsRef<[u8]>>::as_ref(&uc), &iterated[..]);

    // UTF-16
    let uc = c.to_utf16();
    assert_eq!(uc.to_char(), c);
    assert_eq!(uc.hash(sh), c.hash(sh));
    let mut reference_dst = [0;2];
    let mut len = None;
    for i in 0..3 {
        let mut test_dst = [0;2];
        len = c.encode_utf16(&mut reference_dst[..i]);
        assert_eq!(c.to_utf16_slice(&mut test_dst[..i]), len);
        assert_eq!(test_dst, reference_dst);
        assert_eq!(uc.to_slice(&mut test_dst[..i]), len);
        assert_eq!(test_dst, reference_dst);
    }
    let len = len.unwrap();
    assert_eq!(reference_dst[0].utf16_needs_extra_unit(), Some(len==2));
    assert_eq!(reference_dst[0].utf16_is_leading_surrogate(), len==2);
    assert_eq!(char::from_utf16_slice(&reference_dst[..len]), Ok((c,len)));
    for other in &EDGES_AND_BETWEEN {
        let other = unsafe{ char::from_u32_unchecked(*other) };
        let uother = other.to_utf16();
        assert_eq!(uc == uother,  c == other);
        assert_eq!(uc.hash(sh)==other.hash(sh),  c.hash(sh)==uother.hash(sh));
        assert_eq!(uc.cmp(&uother), c.cmp(&other));
    }
    let tuple = c.to_utf16_tuple();
    assert_eq!([tuple.0, tuple.1.unwrap_or(0)],  reference_dst);
    assert_eq!(char::from_utf16_tuple(tuple), Ok(c));
    assert_eq!(c.to_utf16().to_char(), c);
    assert_eq!(c.iter_utf16_units().len(), len);
    let iterated: Vec<_> = c.iter_utf16_units().collect();
    assert_eq!(*iterated, reference_dst[0..len]);
    assert_eq!(<AsRef<[u16]>>::as_ref(&uc), &iterated[..]);
}

#[test]
fn edges_middle() {
    for c in &EDGES_AND_BETWEEN {
        test(*c);
    }
}

#[test]
#[ignore]
fn all() {
    for c in std::iter::Iterator::chain(0..0xd800, 0xe000..0x110000) {
        test(c);
    }
}
<commit_msg>Make tests compile again (and pass)<commit_after>/* Copyright 2016 Torbjørn Birch Moltu
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://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.
 */

#![feature(unicode)]// reference implementations of to_slice

//! Test that every method gives the correct result for valid values.
//! Except iterators, which are stateful.

use std::char;
use std::str::{self,FromStr};
use std::hash::{Hash,SipHasher};
extern crate encode_unicode;
use encode_unicode::*;

#[test]
fn equal_defaults() {
    assert_eq!(Utf8Char::default().to_char(), char::default());
    assert_eq!(Utf16Char::default().to_char(), char::default());
}

#[test]
fn same_size_as_char() {
    use std::mem::size_of;
    assert_eq!(size_of::<Utf8Char>(), size_of::<char>());
    assert_eq!(size_of::<Utf16Char>(), size_of::<char>());
}

const EDGES_AND_BETWEEN: [u32;13] = [
    0x0,// min
    0x3b,// between
    0x7f,// max 1-byte UTF-8
    0x80,// min 2-byte UTF-8
    0x111,// between
    0x7ff,// max 2-byte UTF-8
    0x800,// min 3-byte UTF-8
    0xd7ff,// before reserved
    0xe000,// after reserved
    0xffff,// max UTF-16 single and 3-byte UTF-8
    0x10000,// min UTF-16 surrogate and 4-byte UTF-8
    0xabcde,// between
    0x10ffff,// max
];

fn eq_cmp_hash(c: char) -> (Utf8Char, Utf16Char) {
    let sh = &mut SipHasher::new();
    let u8c = c.to_utf8();
    assert_eq!(u8c.to_char(), c);
    assert_eq!(u8c.hash(sh), c.hash(sh));
    let u16c = c.to_utf16();
    assert_eq!(u16c.to_char(), c);
    assert_eq!(u16c.hash(sh), c.hash(sh));

    for other in &EDGES_AND_BETWEEN {
        let other = unsafe{ char::from_u32_unchecked(*other) };

        let u8other = other.to_utf8();
        assert_eq!(u8c == u8other,  c == other);
        assert_eq!(u8c.hash(sh)==other.hash(sh),  c.hash(sh)==u8other.hash(sh));
        assert_eq!(u8c.cmp(&u8other), c.cmp(&other));

        let u16other = other.to_utf16();
        assert_eq!(u16c == u16other,  c == other);
        assert_eq!(u16c.hash(sh)==other.hash(sh),  c.hash(sh)==u16other.hash(sh));
        assert_eq!(u16c.cmp(&u16other), c.cmp(&other));
    }
    (u8c, u16c)
}

fn iterators(c: char) {
    let mut iter = c.iter_utf8_bytes();
    let mut iter_ref = c.encode_utf8();
    for _ in 0..6 {
        assert_eq!(iter.size_hint(), iter_ref.size_hint());
        assert_eq!(iter.next(), iter_ref.next());
    }

    let mut iter = c.iter_utf16_units();
    let mut iter_ref = c.encode_utf16();
    for _ in 0..4 {
        assert_eq!(iter.size_hint(), iter_ref.size_hint());
        assert_eq!(iter.next(), iter_ref.next());
    }
}

fn test(c: u32) {
    let c = char::from_u32(c).expect(&format!("{:x} is not a valid char", c));
    assert_eq!(char::from_u32_detailed(c as u32), Ok(c));
    let (u8c, u16c) = eq_cmp_hash(c);
    iterators(c);

    // UTF-8
    let reference = c.encode_utf8();
    let reference = reference.as_slice();
    let len = reference.len(); // short name because it is used in many places.
    assert_eq!(reference[0].extra_utf8_bytes(), Ok(len-1));
    assert_eq!(reference[0].extra_utf8_bytes_unchecked(), len-1);

    for i in c.len_utf8()..5 {
        let mut test_dst = [b'F';4];
        assert_eq!(c.to_utf8_slice(&mut test_dst[..i]), len);
        for b in &mut test_dst[len..] {// Test that it doesn't write too much
            assert_eq!(*b, b'F', "c={:?}, i={}, utf8_len={}", c, i, len);
            *b = 0;
        }
        assert_eq!(&test_dst[..len], reference);
        assert_eq!(AsRef::<[u8]>::as_ref(&u8c), reference);
        assert_eq!(u8c.to_array(), (test_dst, len));
    }
    let (arr,arrlen) = u8c.to_array();
    assert_eq!(arrlen, len);
    assert_eq!(Utf8Char::from_array(arr), Ok(u8c));
    assert_eq!(c.to_utf8_array(),  (arr, len));
    assert_eq!(Utf8Char::from_slice_start(&arr), Ok((u8c,len)));// Test that it doesn't read too much
    assert_eq!(Utf8Char::from_slice_start(reference), Ok((u8c,len)));

    let str_ = str::from_utf8(reference).unwrap();
    let ustr = Utf8Char::from_str(str_).unwrap();
    assert_eq!(ustr.to_array().0, arr);// bitwise equality
    assert_eq!(char::from_utf8_array(arr), Ok(c));
    assert_eq!(char::from_utf8_slice(reference), Ok((c,len)));

    // UTF-16
    let reference = c.encode_utf16();
    let reference = reference.as_slice();
    let len = reference.len();
    for i in c.len_utf16()..3 {
        let mut test_dst = [0;2];
        assert_eq!(c.to_utf16_slice(&mut test_dst[..i]), len);
        assert_eq!(&test_dst[..len], reference);
        assert_eq!(u16c.to_slice(&mut test_dst[..i]), len);
    }
    assert_eq!(reference[0].utf16_needs_extra_unit(), Some(len==2));
    assert_eq!(reference[0].utf16_is_leading_surrogate(), len==2);
    assert_eq!(char::from_utf16_slice(&reference[..len]), Ok((c,len)));
    let tuple = c.to_utf16_tuple();
    assert_eq!(tuple, (reference[0],reference.get(1).cloned()));
    assert_eq!(char::from_utf16_tuple(tuple), Ok(c));
    assert_eq!(c.to_utf16().to_char(), c);
}

#[test]
fn edges_middle() {
    for c in &EDGES_AND_BETWEEN {
        test(*c);
    }
}

#[test]
#[ignore]
fn all() {
    for c in std::iter::Iterator::chain(0..0xd800, 0xe000..0x110000) {
        test(c);
    }
}
<|endoftext|>


<commit_before>//! A stack type with heap-allocated contents.
//!
//! MinStacks have amortized `O(1)` push, pop and min (return the minimum value
//! in the stack).

use std::cmp::PartialEq;
use std::cmp::PartialOrd;

pub struct MinStack<T> {
    stack: Vec<T>,
    min_stack: Vec<T>
}

impl<T : Copy + PartialEq + PartialOrd> MinStack<T> {
    /// Constructs a new, empty `MinStack<T>`.
    ///
    /// # Examples
    ///
    /// ```
    /// use minstack::MinStack;
    ///
    /// let mut stack: MinStack<i32> = MinStack::new();
    /// ```
    #[inline]
    pub fn new() -> MinStack<T> {
        MinStack {
            stack: Vec::new(),
            min_stack: Vec::new()
        }
    }

    /// Appends an element to end of the stack.
    ///
    /// # Panics
    ///
    /// Panics if the number of elements in the vector overflows a `usize`.
    ///
    /// # Examples
    ///
    /// ```
    /// use minstack::MinStack;
    ///
    /// let mut stack = MinStack::new();
    /// stack.push(3);
    /// assert_eq!(Some(3), stack.pop());
    /// ```
    #[inline]
    pub fn push(&mut self, value: T) {
        self.stack.push(value);
        match self.min_stack.last() {
            Some(min) if *min < value => { return; },
            _ => { }
        }
        self.min_stack.push(value);
    }

    #[inline]
    fn should_pop_min(&self, value: &Option<T>) -> bool {
        match *value {
            Some(v) => match self.min_stack.last() {
                Some(min) => *min == v,
                None => false
            },
            None => false
        }
    }

    /// Removes the last element from the stack and returns it, or `None` if it
    /// is empty.
    ///
    /// # Examples
    ///
    /// ```
    /// use minstack::MinStack;
    ///
    /// let mut stack = MinStack::new();
    /// stack.push(3);
    /// assert_eq!(Some(3), stack.pop());
    /// assert_eq!(None, stack.pop());
    /// ```
    #[inline]
    pub fn pop(&mut self) -> Option<T> {
        let value = self.stack.pop();

        if self.should_pop_min(&value) {
            self.min_stack.pop();
        }
        value
    }

    /// Returns the smallest element in the stack, or `None` if it is empty.
    ///
    /// # Examples
    ///
    /// ```
    /// use minstack::MinStack;
    ///
    /// let mut stack = MinStack::new();
    /// assert_eq!(None, stack.min());
    /// stack.push(3);
    /// stack.push(1);
    /// stack.push(83);
    /// assert_eq!(Some(&1), stack.min());
    /// ```
    #[inline]
    #[inline]
    pub fn min(&self) -> Option<&T> {
        return self.min_stack.last();
    }
}

#[test]
fn empty_stack() {
    let mut stack : MinStack<i32> = MinStack::new();
    assert_eq!(None, stack.min());
    assert_eq!(None, stack.pop());
}

#[test]
fn ascending_push() {
    let mut stack : MinStack<i32> = MinStack::new();
    stack.push(1);
    stack.push(2);
    stack.push(3);
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(3), stack.pop());
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(2), stack.pop());
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(1), stack.pop());
    assert_eq!(None, stack.min());
    assert_eq!(None, stack.pop());
}

#[test]
fn decending_push() {
    let mut stack : MinStack<i32> = MinStack::new();
    stack.push(3);
    stack.push(2);
    stack.push(1);
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(1), stack.pop());
    assert_eq!(Some(&2), stack.min());
    assert_eq!(Some(2), stack.pop());
    assert_eq!(Some(&3), stack.min());
    assert_eq!(Some(3), stack.pop());
    assert_eq!(None, stack.min());
    assert_eq!(None, stack.pop());
}

#[test]
fn duplicate_push() {
    let mut stack : MinStack<i32> = MinStack::new();
    stack.push(1);
    stack.push(2);
    stack.push(1);
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(1), stack.pop());
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(2), stack.pop());
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(1), stack.pop());
    assert_eq!(None, stack.min());
    assert_eq!(None, stack.pop());
}
<commit_msg>Made the code a bit clearer.<commit_after>//! A stack type with heap-allocated contents.
//!
//! MinStacks have amortized `O(1)` push, pop and min (return the minimum value
//! in the stack).

use std::cmp::PartialEq;
use std::cmp::PartialOrd;

pub struct MinStack<T> {
    stack: Vec<T>,
    // Maintain a parallel stack of minimum values.
    // Whenever a value is pushed to `stack`, also push it to `min_stack` if
    // the value is <= the value at the top of `min_stack`.
    // Whenever a value is popped from `stack`, also pop `min_stack` if the
    // value == the value at the top of `min_stack`.
    min_stack: Vec<T>
}

impl<T : Copy + PartialEq + PartialOrd> MinStack<T> {
    /// Constructs a new, empty `MinStack<T>`.
    ///
    /// # Examples
    ///
    /// ```
    /// use minstack::MinStack;
    ///
    /// let mut stack: MinStack<i32> = MinStack::new();
    /// ```
    #[inline]
    pub fn new() -> MinStack<T> {
        MinStack {
            stack: Vec::new(),
            min_stack: Vec::new()
        }
    }

    /// Appends an element to end of the stack.
    ///
    /// # Panics
    ///
    /// Panics if the number of elements in the vector overflows a `usize`.
    ///
    /// # Examples
    ///
    /// ```
    /// use minstack::MinStack;
    ///
    /// let mut stack = MinStack::new();
    /// stack.push(3);
    /// assert_eq!(Some(3), stack.pop());
    /// ```
    #[inline]
    pub fn push(&mut self, value: T) {
        self.stack.push(value);
        match self.min_stack.last() {
            Some(min) if *min < value => { return; },
            _ => { }
        }
        self.min_stack.push(value);
    }

    #[inline]
    fn should_pop_min(&self, popped_value: &Option<T>) -> bool {
        match *popped_value {
            Some(v) => match self.min_stack.last() {
                Some(min) => *min == v,
                None => false
            },
            None => false
        }
    }

    /// Removes the last element from the stack and returns it, or `None` if it
    /// is empty.
    ///
    /// # Examples
    ///
    /// ```
    /// use minstack::MinStack;
    ///
    /// let mut stack = MinStack::new();
    /// stack.push(3);
    /// assert_eq!(Some(3), stack.pop());
    /// assert_eq!(None, stack.pop());
    /// ```
    #[inline]
    pub fn pop(&mut self) -> Option<T> {
        let value = self.stack.pop();

        if self.should_pop_min(&value) {
            self.min_stack.pop();
        }
        value
    }

    /// Returns the smallest element in the stack, or `None` if it is empty.
    ///
    /// # Examples
    ///
    /// ```
    /// use minstack::MinStack;
    ///
    /// let mut stack = MinStack::new();
    /// assert_eq!(None, stack.min());
    /// stack.push(3);
    /// stack.push(1);
    /// stack.push(83);
    /// assert_eq!(Some(&1), stack.min());
    /// ```
    #[inline]
    #[inline]
    pub fn min(&self) -> Option<&T> {
        return self.min_stack.last();
    }
}

#[test]
fn empty_stack() {
    let mut stack : MinStack<i32> = MinStack::new();
    assert_eq!(None, stack.min());
    assert_eq!(None, stack.pop());
}

#[test]
fn ascending_push() {
    let mut stack : MinStack<i32> = MinStack::new();
    stack.push(1);
    stack.push(2);
    stack.push(3);
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(3), stack.pop());
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(2), stack.pop());
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(1), stack.pop());
    assert_eq!(None, stack.min());
    assert_eq!(None, stack.pop());
}

#[test]
fn decending_push() {
    let mut stack : MinStack<i32> = MinStack::new();
    stack.push(3);
    stack.push(2);
    stack.push(1);
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(1), stack.pop());
    assert_eq!(Some(&2), stack.min());
    assert_eq!(Some(2), stack.pop());
    assert_eq!(Some(&3), stack.min());
    assert_eq!(Some(3), stack.pop());
    assert_eq!(None, stack.min());
    assert_eq!(None, stack.pop());
}

#[test]
fn duplicate_push() {
    let mut stack : MinStack<i32> = MinStack::new();
    stack.push(1);
    stack.push(2);
    stack.push(1);
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(1), stack.pop());
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(2), stack.pop());
    assert_eq!(Some(&1), stack.min());
    assert_eq!(Some(1), stack.pop());
    assert_eq!(None, stack.min());
    assert_eq!(None, stack.pop());
}
<|endoftext|>


<commit_before>use crate::atlas_cache::AtlasCache;
use crate::backend::Backend;
use crate::{Builder, Core, FontData, ImageBuffer, ImageData, SubImageSpec};
use crate::{Flick, FLICKS_PER_SECOND};
use euclid::{size2, Size2D};
use std::error::Error;
use std::sync::Mutex;

pub type ImageKey = SubImageSpec<String>;

/// Toplevel type for current program GUI state.
///
/// Parametrized on a shared application state type T.
pub trait Scene<T> {
    /// Update the logic for this scene.
    ///
    /// May be called several times for one `render` call. Return value tells if this update should
    /// be followed by a change of scene.
    fn update(&mut self, ctx: &mut T) -> Option<SceneSwitch<T>>;

    /// Draw this scene to a Vitral core.
    ///
    /// Render is separate from update for frame rate regulation reasons. If drawing is slow,
    /// multiple updates will be run for one render call.
    ///
    /// The render method can also introduce scene transitions in case there is immediate mode GUI
    /// logic written in the render code.
    fn render(&mut self, ctx: &mut T, core: &mut Core) -> Option<SceneSwitch<T>>;

    /// Process an input event.
    fn input(&mut self, _ctx: &mut T, _event: Evt) {}

    /// Return true if the scene below this one in the scene stack should be visible.
    ///
    /// Is true for scenes that implement a pop-up element instead of a full-screen scene.
    fn draw_previous(&self) -> bool { false }
}

/// Scene transition description.
pub enum SceneSwitch<T> {
    /// Exit from current scene and return to the previous one on the scene stack.
    Pop,
    /// Push a new scene on top of this one.
    Push(Box<dyn Scene<T>>),
    /// Replace this one with a different scene on the top of the stack.
    Replace(Box<dyn Scene<T>>),
}

#[derive(Clone, Debug)]
pub enum Evt {
    // TODO: Key-down, key-up, key-typed, mouse events
}

pub struct AppConfig {
    pub frame_duration: Flick,
    pub resolution: Size2D<u32>,
    pub window_title: String,
}

impl AppConfig {
    pub fn new(title: impl Into<String>) -> AppConfig {
        AppConfig {
            frame_duration: Flick(FLICKS_PER_SECOND / 30),
            resolution: size2(640, 360),
            window_title: title.into(),
        }
    }
}

#[derive(Default)]
struct EngineState {
    // TODO: Save last frame image for screenshotting here. (Just store the render buffer inside
    // EngineState all the while?)
    atlas_cache: AtlasCache<String>,
}

impl EngineState {
    fn new() -> EngineState {
        // TODO: Change to Default::default() once solid pixel is generated through atlasing.
        // The starting index needs to be set to 1 instead of 0 to account for the kludged-up
        // separate texture for the solid pixel currently in.
        EngineState {
            atlas_cache: AtlasCache::new(1024, 1),
        }
    }
}

lazy_static! {
    /// Global game engine state.
    static ref ENGINE_STATE: Mutex<EngineState> = { Mutex::new(EngineState::new()) };
}

/// Start running a Scene state machine app with the given configuration.
pub fn run_app<T>(
    config: AppConfig,
    world: T,
    scenes: Vec<Box<dyn Scene<T>>>,
) -> Result<(), Box<dyn Error>> {
    // TODO: Maybe want world to come in as &mut T instead of T in the future so that the caller
    // can access it after run_app finishes? Or just return the world if exit is successful?
    let backend = Backend::start(
        config.resolution.width,
        config.resolution.height,
        config.window_title,
    )?;

    let mut gameloop = GameLoop::new(backend, world, scenes).frame_duration(config.frame_duration);

    gameloop.run();

    Ok(())
}

/// Saves a screenshot with the given name prefix to disk.
///
/// Panics if called when an app isn't running via `run_app`.
pub fn save_screenshot(_prefix: &str) -> Result<(), Box<dyn Error>> {
    unimplemented!();
}

/// Return the average frame duration for recent frames.
///
/// Panics if called when an app isn't running via `run_app`.
pub fn get_frame_duration() -> Flick {
    unimplemented!();
}

/// Add a named image into the engine image atlas.
pub fn add_sheet(id: impl Into<String>, sheet: impl Into<ImageBuffer>) -> ImageKey {
    ENGINE_STATE
        .lock()
        .unwrap()
        .atlas_cache
        .add_sheet(id, sheet)
}

/// Add a tilesheet image that gets automatically split to subimages based on image structure.
///
/// Tiles are bounding boxes of non-background pixel groups surrounded by only background pixels or
/// image edges. Background color is the color of the bottom right corner pixel of the image. The
/// bounding boxes are returned lexically sorted by the coordinates of their bottom right corners,
/// first along the y-axis then along the x-axis. This produces a natural left-to-right,
/// bottom-to-top ordering for a cleanly laid out tile sheet.
///
/// Note that the background color is a solid color, not transparent pixels. The inner tiles may
/// have transparent parts, so a solid color is needed to separate them.
pub fn add_tilesheet(
    id: impl Into<String>,
    sheet: impl Into<ImageBuffer>,
    _span: impl IntoIterator<Item = char>,
) -> Vec<ImageKey> {
    ENGINE_STATE
        .lock()
        .unwrap()
        .atlas_cache
        .add_tilesheet(id, sheet)
}

/// Add a bitmap font read from a tilesheet image.
pub fn add_tilesheet_font(
    id: impl Into<String>,
    sheet: impl Into<ImageBuffer>,
    span: impl IntoIterator<Item = char>,
) -> FontData {
    ENGINE_STATE
        .lock()
        .unwrap()
        .atlas_cache
        .add_tilesheet_font(id, sheet, span)
}

/// Get a drawable (sub)image from the cache corresponding to the given `ImageKey`.
///
/// If the `ImageKey` specifies a sheet not found in the cache or invalid dimensions, will return
/// `None`.
pub fn get_image(key: &ImageKey) -> Option<ImageData> {
    // TODO: Convert AtlasCache::get to match this API instead of panicing at failure
    // (Best done when conversion to new gameloop is done and AtlasCache API isn't used publicly
    // anymore.)
    Some(ENGINE_STATE.lock().unwrap().atlas_cache.get(key).clone())
}

/// `Scene` stack based game loop runner.
pub struct GameLoop<T> {
    frame_duration: Flick,
    scene_stack: Vec<Box<dyn Scene<T>>>,
    world: T,
    backend: Backend,
    core: Core,
}

impl<T> GameLoop<T> {
    pub fn new(mut backend: Backend, world: T, scenes: Vec<Box<dyn Scene<T>>>) -> GameLoop<T> {
        // TODO: Handle solid texture in atlaser. When it's first requested, generate it as a
        // single solid pixel in the atlas page currently being filled.
        let core = Builder::new().build(backend.canvas_size(), |img| backend.make_texture(img));

        GameLoop {
            frame_duration: Flick(FLICKS_PER_SECOND / 30),
            scene_stack: scenes,
            world,
            backend,
            core,
        }
    }

    pub fn frame_duration(mut self, frame_duration: Flick) -> Self {
        self.frame_duration = frame_duration;
        self
    }

    fn update(&mut self) {
        let top = self.scene_stack.len() - 1;
        let ret = self.scene_stack[top].update(&mut self.world);
        self.process(ret);
    }

    fn process(&mut self, switch: Option<SceneSwitch<T>>) {
        let top = self.scene_stack.len() - 1;
        match switch {
            Some(SceneSwitch::Pop) => {
                self.scene_stack.pop();
            }
            Some(SceneSwitch::Push(scene)) => {
                self.scene_stack.push(scene);
            }
            Some(SceneSwitch::Replace(scene)) => {
                self.scene_stack[top] = scene;
            }
            None => {}
        }
    }

    fn render(&mut self) {
        // Find the lowest scene from top with only transparent scenes on top of it.
        let end = self.scene_stack.len();
        let mut begin = end - 1;
        while begin > 0 && self.scene_stack[begin].draw_previous() {
            begin -= 1;
        }

        let mut switch = None;
        for i in begin..end {
            // Only the switch result from the topmost state counts here.
            switch = self.scene_stack[i].render(&mut self.world, &mut self.core);
        }
        self.process(switch);
    }

    pub fn run(&mut self) {
        // Inspired by https://gafferongames.com/post/fix_your_timestep/
        let mut t = Flick::now();
        let mut accum = Flick(0);
        'gameloop: loop {
            let new_t = Flick::now();
            let frame_duration = new_t - t;
            t = new_t;

            accum += frame_duration;

            while accum >= self.frame_duration {
                self.update();
                accum -= self.frame_duration;
                if self.scene_stack.is_empty() {
                    break 'gameloop;
                }
            }

            self.backend
                .sync_with_atlas_cache(&mut ENGINE_STATE.lock().unwrap().atlas_cache);

            self.render();
            if self.scene_stack.is_empty() {
                break 'gameloop;
            }

            if !self.backend.update(&mut self.core) {
                break;
            }
        }
        // TODO: Some kind of return value.
    }
}
<commit_msg>Frame duration setting API<commit_after>use crate::atlas_cache::AtlasCache;
use crate::backend::Backend;
use crate::{Builder, Core, FontData, ImageBuffer, ImageData, SubImageSpec};
use crate::{Flick, FLICKS_PER_SECOND};
use euclid::{size2, Size2D};
use std::error::Error;
use std::sync::Mutex;

pub type ImageKey = SubImageSpec<String>;

/// Toplevel type for current program GUI state.
///
/// Parametrized on a shared application state type T.
pub trait Scene<T> {
    /// Update the logic for this scene.
    ///
    /// May be called several times for one `render` call. Return value tells if this update should
    /// be followed by a change of scene.
    fn update(&mut self, ctx: &mut T) -> Option<SceneSwitch<T>>;

    /// Draw this scene to a Vitral core.
    ///
    /// Render is separate from update for frame rate regulation reasons. If drawing is slow,
    /// multiple updates will be run for one render call.
    ///
    /// The render method can also introduce scene transitions in case there is immediate mode GUI
    /// logic written in the render code.
    fn render(&mut self, ctx: &mut T, core: &mut Core) -> Option<SceneSwitch<T>>;

    /// Process an input event.
    fn input(&mut self, _ctx: &mut T, _event: Evt) {}

    /// Return true if the scene below this one in the scene stack should be visible.
    ///
    /// Is true for scenes that implement a pop-up element instead of a full-screen scene.
    fn draw_previous(&self) -> bool { false }
}

/// Scene transition description.
pub enum SceneSwitch<T> {
    /// Exit from current scene and return to the previous one on the scene stack.
    Pop,
    /// Push a new scene on top of this one.
    Push(Box<dyn Scene<T>>),
    /// Replace this one with a different scene on the top of the stack.
    Replace(Box<dyn Scene<T>>),
}

#[derive(Clone, Debug)]
pub enum Evt {
    // TODO: Key-down, key-up, key-typed, mouse events
}

pub struct AppConfig {
    pub frame_duration: Flick,
    pub resolution: Size2D<u32>,
    pub window_title: String,
}

impl AppConfig {
    pub fn new(title: impl Into<String>) -> AppConfig {
        AppConfig {
            frame_duration: Flick(FLICKS_PER_SECOND / 30),
            resolution: size2(640, 360),
            window_title: title.into(),
        }
    }

    pub fn frame_duration(mut self, frame_duration: Flick) -> AppConfig
    {
        self.frame_duration = frame_duration;
        return self
    }
}

#[derive(Default)]
struct EngineState {
    // TODO: Save last frame image for screenshotting here. (Just store the render buffer inside
    // EngineState all the while?)
    atlas_cache: AtlasCache<String>,
}

impl EngineState {
    fn new() -> EngineState {
        // TODO: Change to Default::default() once solid pixel is generated through atlasing.
        // The starting index needs to be set to 1 instead of 0 to account for the kludged-up
        // separate texture for the solid pixel currently in.
        EngineState {
            atlas_cache: AtlasCache::new(1024, 1),
        }
    }
}

lazy_static! {
    /// Global game engine state.
    static ref ENGINE_STATE: Mutex<EngineState> = { Mutex::new(EngineState::new()) };
}

/// Start running a Scene state machine app with the given configuration.
pub fn run_app<T>(
    config: AppConfig,
    world: T,
    scenes: Vec<Box<dyn Scene<T>>>,
) -> Result<(), Box<dyn Error>> {
    // TODO: Maybe want world to come in as &mut T instead of T in the future so that the caller
    // can access it after run_app finishes? Or just return the world if exit is successful?
    let backend = Backend::start(
        config.resolution.width,
        config.resolution.height,
        config.window_title,
    )?;

    let mut gameloop = GameLoop::new(backend, world, scenes).frame_duration(config.frame_duration);

    gameloop.run();

    Ok(())
}

/// Saves a screenshot with the given name prefix to disk.
///
/// Panics if called when an app isn't running via `run_app`.
pub fn save_screenshot(_prefix: &str) -> Result<(), Box<dyn Error>> {
    unimplemented!();
}

/// Return the average frame duration for recent frames.
///
/// Panics if called when an app isn't running via `run_app`.
pub fn get_frame_duration() -> Flick {
    unimplemented!();
}

/// Add a named image into the engine image atlas.
pub fn add_sheet(id: impl Into<String>, sheet: impl Into<ImageBuffer>) -> ImageKey {
    ENGINE_STATE
        .lock()
        .unwrap()
        .atlas_cache
        .add_sheet(id, sheet)
}

/// Add a tilesheet image that gets automatically split to subimages based on image structure.
///
/// Tiles are bounding boxes of non-background pixel groups surrounded by only background pixels or
/// image edges. Background color is the color of the bottom right corner pixel of the image. The
/// bounding boxes are returned lexically sorted by the coordinates of their bottom right corners,
/// first along the y-axis then along the x-axis. This produces a natural left-to-right,
/// bottom-to-top ordering for a cleanly laid out tile sheet.
///
/// Note that the background color is a solid color, not transparent pixels. The inner tiles may
/// have transparent parts, so a solid color is needed to separate them.
pub fn add_tilesheet(
    id: impl Into<String>,
    sheet: impl Into<ImageBuffer>,
    _span: impl IntoIterator<Item = char>,
) -> Vec<ImageKey> {
    ENGINE_STATE
        .lock()
        .unwrap()
        .atlas_cache
        .add_tilesheet(id, sheet)
}

/// Add a bitmap font read from a tilesheet image.
pub fn add_tilesheet_font(
    id: impl Into<String>,
    sheet: impl Into<ImageBuffer>,
    span: impl IntoIterator<Item = char>,
) -> FontData {
    ENGINE_STATE
        .lock()
        .unwrap()
        .atlas_cache
        .add_tilesheet_font(id, sheet, span)
}

/// Get a drawable (sub)image from the cache corresponding to the given `ImageKey`.
///
/// If the `ImageKey` specifies a sheet not found in the cache or invalid dimensions, will return
/// `None`.
pub fn get_image(key: &ImageKey) -> Option<ImageData> {
    // TODO: Convert AtlasCache::get to match this API instead of panicing at failure
    // (Best done when conversion to new gameloop is done and AtlasCache API isn't used publicly
    // anymore.)
    Some(ENGINE_STATE.lock().unwrap().atlas_cache.get(key).clone())
}

/// `Scene` stack based game loop runner.
pub struct GameLoop<T> {
    frame_duration: Flick,
    scene_stack: Vec<Box<dyn Scene<T>>>,
    world: T,
    backend: Backend,
    core: Core,
}

impl<T> GameLoop<T> {
    pub fn new(mut backend: Backend, world: T, scenes: Vec<Box<dyn Scene<T>>>) -> GameLoop<T> {
        // TODO: Handle solid texture in atlaser. When it's first requested, generate it as a
        // single solid pixel in the atlas page currently being filled.
        let core = Builder::new().build(backend.canvas_size(), |img| backend.make_texture(img));

        GameLoop {
            frame_duration: Flick(FLICKS_PER_SECOND / 30),
            scene_stack: scenes,
            world,
            backend,
            core,
        }
    }

    pub fn frame_duration(mut self, frame_duration: Flick) -> Self {
        self.frame_duration = frame_duration;
        self
    }

    fn update(&mut self) {
        let top = self.scene_stack.len() - 1;
        let ret = self.scene_stack[top].update(&mut self.world);
        self.process(ret);
    }

    fn process(&mut self, switch: Option<SceneSwitch<T>>) {
        let top = self.scene_stack.len() - 1;
        match switch {
            Some(SceneSwitch::Pop) => {
                self.scene_stack.pop();
            }
            Some(SceneSwitch::Push(scene)) => {
                self.scene_stack.push(scene);
            }
            Some(SceneSwitch::Replace(scene)) => {
                self.scene_stack[top] = scene;
            }
            None => {}
        }
    }

    fn render(&mut self) {
        // Find the lowest scene from top with only transparent scenes on top of it.
        let end = self.scene_stack.len();
        let mut begin = end - 1;
        while begin > 0 && self.scene_stack[begin].draw_previous() {
            begin -= 1;
        }

        let mut switch = None;
        for i in begin..end {
            // Only the switch result from the topmost state counts here.
            switch = self.scene_stack[i].render(&mut self.world, &mut self.core);
        }
        self.process(switch);
    }

    pub fn run(&mut self) {
        // Inspired by https://gafferongames.com/post/fix_your_timestep/
        let mut t = Flick::now();
        let mut accum = Flick(0);
        'gameloop: loop {
            let new_t = Flick::now();
            let frame_duration = new_t - t;
            t = new_t;

            accum += frame_duration;

            while accum >= self.frame_duration {
                self.update();
                accum -= self.frame_duration;
                if self.scene_stack.is_empty() {
                    break 'gameloop;
                }
            }

            self.backend
                .sync_with_atlas_cache(&mut ENGINE_STATE.lock().unwrap().atlas_cache);

            self.render();
            if self.scene_stack.is_empty() {
                break 'gameloop;
            }

            if !self.backend.update(&mut self.core) {
                break;
            }
        }
        // TODO: Some kind of return value.
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use common::{Diagnostic, DiagnosticsResult, Location, NamedItem, WithLocation};
use errors::validate;
use graphql_ir::{
    Argument, Directive, Field, FragmentDefinition, LinkedField, OperationDefinition, Program,
    ScalarField, ValidationMessage, Validator,
};
use intern::string_key::{Intern, StringKey};
use lazy_static::lazy_static;
use schema::{ArgumentDefinitions, Schema};

lazy_static! {
    static ref FAT_INTERFACE: StringKey = "fixme_fat_interface".intern();
}

pub fn validate_required_arguments(program: &Program) -> DiagnosticsResult<()> {
    let mut validator = ValidateRequiredArguments::new(program);
    validator.validate_program(program)
}

struct ValidateRequiredArguments<'program> {
    program: &'program Program,
    root_name_with_location: Option<WithLocation<StringKey>>,
}

impl<'program> ValidateRequiredArguments<'program> {
    fn new(program: &'program Program) -> Self {
        Self {
            program,
            root_name_with_location: None,
        }
    }
}

impl Validator for ValidateRequiredArguments<'_> {
    const NAME: &'static str = "ValidateRequiredArguments";
    const VALIDATE_ARGUMENTS: bool = false;
    const VALIDATE_DIRECTIVES: bool = true;

    fn validate_operation(&mut self, operation: &OperationDefinition) -> DiagnosticsResult<()> {
        self.root_name_with_location = Some(operation.name);
        self.default_validate_operation(operation)
    }

    fn validate_fragment(&mut self, fragment: &FragmentDefinition) -> DiagnosticsResult<()> {
        self.root_name_with_location = Some(fragment.name);
        self.default_validate_fragment(fragment)
    }

    fn validate_scalar_field(&mut self, field: &ScalarField) -> DiagnosticsResult<()> {
        let definition = self.program.schema.field(field.definition.item);
        validate!(
            if field.directives.named(*FAT_INTERFACE).is_some() {
                Ok(())
            } else {
                self.validate_required_arguments(
                    &definition.arguments,
                    &field.arguments,
                    field.alias_or_name(&self.program.schema),
                    field.alias_or_name_location(),
                    self.root_name_with_location.unwrap(),
                )
            },
            self.validate_directives(&field.directives)
        )
    }

    fn validate_linked_field(&mut self, field: &LinkedField) -> DiagnosticsResult<()> {
        let definition = self.program.schema.field(field.definition.item);
        validate!(
            if field.directives.named(*FAT_INTERFACE).is_some() {
                Ok(())
            } else {
                self.validate_required_arguments(
                    &definition.arguments,
                    &field.arguments,
                    field.alias_or_name(&self.program.schema),
                    field.alias_or_name_location(),
                    self.root_name_with_location.unwrap(),
                )
            },
            self.default_validate_linked_field(field)
        )
    }

    fn validate_directive(&mut self, directive: &Directive) -> DiagnosticsResult<()> {
        let definition = self.program.schema.get_directive(directive.name.item);
        if let Some(definition) = definition {
            self.validate_required_arguments(
                &definition.arguments,
                &directive.arguments,
                directive.name.item,
                directive.name.location,
                self.root_name_with_location.unwrap(),
            )
        } else {
            Ok(())
        }
    }
}

impl ValidateRequiredArguments<'_> {
    fn validate_required_arguments(
        &self,
        argument_defintinitions: &ArgumentDefinitions,
        arguments: &[Argument],
        node_name: StringKey,
        node_location: Location,
        root_name_with_location: WithLocation<StringKey>,
    ) -> DiagnosticsResult<()> {
        if !argument_defintinitions.is_empty() {
            for def in argument_defintinitions.iter() {
                if def.type_.is_non_null()
                    && def.default_value.is_none()
                    && !arguments
                        .iter()
                        .map(|arg| arg.name.item)
                        .any(|x| x == def.name)
                {
                    return Err(vec![
                        Diagnostic::error(
                            ValidationMessage::MissingRequiredArgument {
                                argument_name: def.name,
                                node_name,
                                root_name: root_name_with_location.item,
                                type_string: self.program.schema.get_type_string(&def.type_),
                            },
                            node_location,
                        )
                        .annotate("Root definition:", root_name_with_location.location),
                    ]);
                }
            }
        }
        Ok(())
    }
}
<commit_msg>typo fix<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use common::{Diagnostic, DiagnosticsResult, Location, NamedItem, WithLocation};
use errors::validate;
use graphql_ir::{
    Argument, Directive, Field, FragmentDefinition, LinkedField, OperationDefinition, Program,
    ScalarField, ValidationMessage, Validator,
};
use intern::string_key::{Intern, StringKey};
use lazy_static::lazy_static;
use schema::{ArgumentDefinitions, Schema};

lazy_static! {
    static ref FAT_INTERFACE: StringKey = "fixme_fat_interface".intern();
}

pub fn validate_required_arguments(program: &Program) -> DiagnosticsResult<()> {
    let mut validator = ValidateRequiredArguments::new(program);
    validator.validate_program(program)
}

struct ValidateRequiredArguments<'program> {
    program: &'program Program,
    root_name_with_location: Option<WithLocation<StringKey>>,
}

impl<'program> ValidateRequiredArguments<'program> {
    fn new(program: &'program Program) -> Self {
        Self {
            program,
            root_name_with_location: None,
        }
    }
}

impl Validator for ValidateRequiredArguments<'_> {
    const NAME: &'static str = "ValidateRequiredArguments";
    const VALIDATE_ARGUMENTS: bool = false;
    const VALIDATE_DIRECTIVES: bool = true;

    fn validate_operation(&mut self, operation: &OperationDefinition) -> DiagnosticsResult<()> {
        self.root_name_with_location = Some(operation.name);
        self.default_validate_operation(operation)
    }

    fn validate_fragment(&mut self, fragment: &FragmentDefinition) -> DiagnosticsResult<()> {
        self.root_name_with_location = Some(fragment.name);
        self.default_validate_fragment(fragment)
    }

    fn validate_scalar_field(&mut self, field: &ScalarField) -> DiagnosticsResult<()> {
        let definition = self.program.schema.field(field.definition.item);
        validate!(
            if field.directives.named(*FAT_INTERFACE).is_some() {
                Ok(())
            } else {
                self.validate_required_arguments(
                    &definition.arguments,
                    &field.arguments,
                    field.alias_or_name(&self.program.schema),
                    field.alias_or_name_location(),
                    self.root_name_with_location.unwrap(),
                )
            },
            self.validate_directives(&field.directives)
        )
    }

    fn validate_linked_field(&mut self, field: &LinkedField) -> DiagnosticsResult<()> {
        let definition = self.program.schema.field(field.definition.item);
        validate!(
            if field.directives.named(*FAT_INTERFACE).is_some() {
                Ok(())
            } else {
                self.validate_required_arguments(
                    &definition.arguments,
                    &field.arguments,
                    field.alias_or_name(&self.program.schema),
                    field.alias_or_name_location(),
                    self.root_name_with_location.unwrap(),
                )
            },
            self.default_validate_linked_field(field)
        )
    }

    fn validate_directive(&mut self, directive: &Directive) -> DiagnosticsResult<()> {
        let definition = self.program.schema.get_directive(directive.name.item);
        if let Some(definition) = definition {
            self.validate_required_arguments(
                &definition.arguments,
                &directive.arguments,
                directive.name.item,
                directive.name.location,
                self.root_name_with_location.unwrap(),
            )
        } else {
            Ok(())
        }
    }
}

impl ValidateRequiredArguments<'_> {
    fn validate_required_arguments(
        &self,
        argument_definitions: &ArgumentDefinitions,
        arguments: &[Argument],
        node_name: StringKey,
        node_location: Location,
        root_name_with_location: WithLocation<StringKey>,
    ) -> DiagnosticsResult<()> {
        if !argument_definitions.is_empty() {
            for def in argument_definitions.iter() {
                if def.type_.is_non_null()
                    && def.default_value.is_none()
                    && !arguments
                        .iter()
                        .map(|arg| arg.name.item)
                        .any(|x| x == def.name)
                {
                    return Err(vec![
                        Diagnostic::error(
                            ValidationMessage::MissingRequiredArgument {
                                argument_name: def.name,
                                node_name,
                                root_name: root_name_with_location.item,
                                type_string: self.program.schema.get_type_string(&def.type_),
                            },
                            node_location,
                        )
                        .annotate("Root definition:", root_name_with_location.location),
                    ]);
                }
            }
        }
        Ok(())
    }
}
<|endoftext|>