<commit_before>use env_logger;
use failure;
use glob;
use home;

use gluon_crates_io;
use gluon_master;

use std::{
    env, fs, io,
    path::{Path, PathBuf},
    process::{self, Command},
};

use regex::Regex;

const LOCK_FILE: &str = include_str!("Cargo.lock");

fn git_master_version() -> String {
    Regex::new(r#"git\+[^#]+gluon#([^"]+)"#)
        .unwrap()
        .captures(LOCK_FILE)
        .expect("gluon master version")
        .get(1)
        .unwrap()
        .as_str()
        .to_string()
}

fn crates_io_version() -> String {
    Regex::new(r"gluon ([^ ]+) \(registry\+")
        .unwrap()
        .captures(LOCK_FILE)
        .expect("gluon master version")
        .get(1)
        .unwrap()
        .as_str()
        .to_string()
}

fn gluon_git_path() -> Result<PathBuf, failure::Error> {
    let std_glob_path = home::cargo_home()?
        .join(&format!(
            "git/checkouts/gluon-*/{}",
            &git_master_version()[..7]
        ))
        .display()
        .to_string();
    Ok(glob::glob(&std_glob_path)?
        .next()
        .expect("git repo in cargo home")?)
}

fn gluon_crates_io_path() -> Result<PathBuf, failure::Error> {
    let std_glob_path = home::cargo_home()?
        .join(&format!("registry/src/*/gluon-{}/", crates_io_version()))
        .display()
        .to_string();
    Ok(glob::glob(&std_glob_path)?
        .map(|result| result.unwrap())
        .max()
        .expect("crates io entry in cargo home"))
}

fn generate_doc_for_dir<P, Q, F>(
    in_dir: &P,
    out_dir: &Q,
    mut generate_doc: F,
) -> Result<(), failure::Error>
where
    P: AsRef<Path> + ?Sized,
    Q: AsRef<Path> + ?Sized,

    F: FnMut(&Path, &Path) -> Result<(), failure::Error>,
{
    generate_doc_for_dir_(in_dir.as_ref(), out_dir.as_ref(), &mut generate_doc)
}

fn generate_doc_for_dir_(
    in_dir: &Path,
    out_dir: &Path,
    generate_doc: &mut dyn FnMut(&Path, &Path) -> Result<(), failure::Error>,
) -> Result<(), failure::Error> {
    {
        eprintln!(
            "Generating gluon doc: {} -> {}",
            in_dir.display(),
            out_dir.display()
        );
        if Path::new("target/std").exists() {
            fs::remove_dir_all("target/std")?;
        }

        let before = env::current_dir()?;
        env::set_current_dir(in_dir)?;
        generate_doc(Path::new("std"), &Path::new("..").join(out_dir).join("std"))?;
        env::set_current_dir(before)?;
    }

    fs::remove_dir_all(out_dir.join("book")).or_else(|err| {
        if err.kind() == io::ErrorKind::NotFound {
            Ok(())
        } else {
            Err(err)
        }
    })?;
    let mut command = Command::new("mdbook");
    command.args(&[
        "build",
        "--dest-dir",
        &env::current_dir()?
            .join(out_dir)
            .join("book")
            .to_string_lossy(),
        &in_dir.join("book").to_string_lossy(),
    ]);
    eprintln!("Building book: {:?}", command);
    let exit_status = command.status()?;
    if !exit_status.success() {
        return Err(failure::err_msg("Error building book docs"));
    }
    Ok(())
}

fn create_docs() -> Result<(), failure::Error> {
    {
        let git_dir = gluon_git_path()?;
        generate_doc_for_dir(&git_dir, "dist/doc/nightly", |input, output| {
            let src_url = Some(format!(
                "https://github.com/gluon-lang/gluon/blob/{}",
                git_master_version()
            ));
            gluon_master::generate_doc(&gluon_master::gluon_doc::Options {
                input: input.to_owned(),
                output: output.to_owned(),
                src_url,
            })
        })?;
    }

    {
        let crates_io_dir = gluon_crates_io_path()?;
        generate_doc_for_dir(
            &crates_io_dir,
            "dist/doc/crates_io",
            gluon_crates_io::generate_doc,
        )?;
    }

    Ok(())
}

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

    if let Err(err) = create_docs() {
        eprintln!("{}\n{}", err.backtrace(), err);
        process::exit(1);
    }
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=Cargo.lock");
}
<commit_msg>Assert that docs are generated<commit_after>use env_logger;
use failure;
use glob;
use home;

use gluon_crates_io;
use gluon_master;

use std::{
    env, fs, io,
    path::{Path, PathBuf},
    process::{self, Command},
};

use regex::Regex;

const LOCK_FILE: &str = include_str!("Cargo.lock");

fn git_master_version() -> String {
    Regex::new(r#"git\+[^#]+gluon#([^"]+)"#)
        .unwrap()
        .captures(LOCK_FILE)
        .expect("gluon master version")
        .get(1)
        .unwrap()
        .as_str()
        .to_string()
}

fn crates_io_version() -> String {
    Regex::new(r"gluon ([^ ]+) \(registry\+")
        .unwrap()
        .captures(LOCK_FILE)
        .expect("gluon master version")
        .get(1)
        .unwrap()
        .as_str()
        .to_string()
}

fn gluon_git_path() -> Result<PathBuf, failure::Error> {
    let std_glob_path = home::cargo_home()?
        .join(&format!(
            "git/checkouts/gluon-*/{}",
            &git_master_version()[..7]
        ))
        .display()
        .to_string();
    Ok(glob::glob(&std_glob_path)?
        .next()
        .expect("git repo in cargo home")?)
}

fn gluon_crates_io_path() -> Result<PathBuf, failure::Error> {
    let std_glob_path = home::cargo_home()?
        .join(&format!("registry/src/*/gluon-{}/", crates_io_version()))
        .display()
        .to_string();
    Ok(glob::glob(&std_glob_path)?
        .map(|result| result.unwrap())
        .max()
        .expect("crates io entry in cargo home"))
}

fn generate_doc_for_dir<P, Q, F>(
    in_dir: &P,
    out_dir: &Q,
    mut generate_doc: F,
) -> Result<(), failure::Error>
where
    P: AsRef<Path> + ?Sized,
    Q: AsRef<Path> + ?Sized,

    F: FnMut(&Path, &Path) -> Result<(), failure::Error>,
{
    generate_doc_for_dir_(in_dir.as_ref(), out_dir.as_ref(), &mut generate_doc)
}

fn generate_doc_for_dir_(
    in_dir: &Path,
    out_dir: &Path,
    generate_doc: &mut dyn FnMut(&Path, &Path) -> Result<(), failure::Error>,
) -> Result<(), failure::Error> {
    {
        eprintln!(
            "Generating gluon doc: {} -> {}",
            in_dir.display(),
            out_dir.display()
        );
        if Path::new("target/std").exists() {
            fs::remove_dir_all("target/std")?;
        }

        let before = env::current_dir()?;
        env::set_current_dir(in_dir)?;
        generate_doc(Path::new("std"), &Path::new("..").join(out_dir).join("std"))?;
        env::set_current_dir(before)?;
    }

    fs::remove_dir_all(out_dir.join("book")).or_else(|err| {
        if err.kind() == io::ErrorKind::NotFound {
            Ok(())
        } else {
            Err(err)
        }
    })?;
    let mut command = Command::new("mdbook");
    command.args(&[
        "build",
        "--dest-dir",
        &env::current_dir()?
            .join(out_dir)
            .join("book")
            .to_string_lossy(),
        &in_dir.join("book").to_string_lossy(),
    ]);
    eprintln!("Building book: {:?}", command);
    let exit_status = command.status()?;
    if !exit_status.success() {
        return Err(failure::err_msg("Error building book docs"));
    }
    Ok(())
}

fn create_docs() -> Result<(), failure::Error> {
    {
        let git_dir = gluon_git_path()?;
        generate_doc_for_dir(&git_dir, "dist/doc/nightly", |input, output| {
            let src_url = Some(format!(
                "https://github.com/gluon-lang/gluon/blob/{}",
                git_master_version()
            ));
            gluon_master::generate_doc(&gluon_master::gluon_doc::Options {
                input: input.to_owned(),
                output: output.to_owned(),
                src_url,
            })
        })?;
        assert!(Path::new("dist/doc/nightly/std/std.html").exists());
    }

    {
        let crates_io_dir = gluon_crates_io_path()?;
        generate_doc_for_dir(
            &crates_io_dir,
            "dist/doc/crates_io",
            gluon_crates_io::generate_doc,
        )?;
        assert!(Path::new("dist/doc/crates_io/std/std.html").exists());
    }

    Ok(())
}

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

    if let Err(err) = create_docs() {
        eprintln!("{}\n{}", err.backtrace(), err);
        process::exit(1);
    }
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=Cargo.lock");
}
<|endoftext|>


<commit_before>use git2::Repository;
use std::env;
use std::fs::{self, File};
use std::io::Write;
use std::path::Path;

fn main() {
    // Set the host target
    println!(
        "cargo:rustc-env=CRATESFYI_HOST_TARGET={}",
        env::var("TARGET").unwrap()
    );

    write_git_version();
    compile_sass();
    copy_js();
}

fn write_git_version() {
    let git_hash = get_git_hash().unwrap_or("???????".to_owned());
    let build_date = time::strftime("%Y-%m-%d", &time::now_utc()).unwrap();
    let dest_path = Path::new(&env::var("OUT_DIR").unwrap()).join("git_version");

    let mut file = File::create(&dest_path).unwrap();
    write!(file, "({} {})", git_hash, build_date).unwrap();
}

fn get_git_hash() -> Option<String> {
    let repo = Repository::open(env::current_dir().unwrap()).ok()?;
    let head = repo.head().unwrap();

    head.target().map(|h| {
        let mut h = format!("{}", h);
        h.truncate(7);
        h
    })
}

fn compile_sass() {
    use sass_rs::Context;

    let mut file_context =
        Context::new_file(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/style.scss")).unwrap();
    let css = file_context.compile().unwrap();
    let dest_path = Path::new(&env::var("OUT_DIR").unwrap()).join("style.css");
    let mut file = File::create(&dest_path).unwrap();
    file.write_all(css.as_bytes()).unwrap();
}

fn copy_js() {
    ["menu.js", "index.js"].iter().for_each(|path| {
        let source_path =
            Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join(format!("templates/{}", path));
        let dest_path = Path::new(&env::var("OUT_DIR").unwrap()).join(path);
        fs::copy(&source_path, &dest_path).expect("Copy JavaScript file to target");
    });
}
<commit_msg>Remove unnecessary clone<commit_after>use git2::Repository;
use std::env;
use std::fs::{self, File};
use std::io::Write;
use std::path::Path;

fn main() {
    // Set the host target
    println!(
        "cargo:rustc-env=CRATESFYI_HOST_TARGET={}",
        env::var("TARGET").unwrap()
    );

    write_git_version();
    compile_sass();
    copy_js();
}

fn write_git_version() {
    let maybe_hash = get_git_hash();
    let git_hash = maybe_hash.as_deref().unwrap_or("???????");
    let build_date = time::strftime("%Y-%m-%d", &time::now_utc()).unwrap();
    let dest_path = Path::new(&env::var("OUT_DIR").unwrap()).join("git_version");

    let mut file = File::create(&dest_path).unwrap();
    write!(file, "({} {})", git_hash, build_date).unwrap();
}

fn get_git_hash() -> Option<String> {
    let repo = Repository::open(env::current_dir().unwrap()).ok()?;
    let head = repo.head().unwrap();

    head.target().map(|h| {
        let mut h = format!("{}", h);
        h.truncate(7);
        h
    })
}

fn compile_sass() {
    use sass_rs::Context;

    let mut file_context =
        Context::new_file(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/style.scss")).unwrap();
    let css = file_context.compile().unwrap();
    let dest_path = Path::new(&env::var("OUT_DIR").unwrap()).join("style.css");
    let mut file = File::create(&dest_path).unwrap();
    file.write_all(css.as_bytes()).unwrap();
}

fn copy_js() {
    ["menu.js", "index.js"].iter().for_each(|path| {
        let source_path =
            Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join(format!("templates/{}", path));
        let dest_path = Path::new(&env::var("OUT_DIR").unwrap()).join(path);
        fs::copy(&source_path, &dest_path).expect("Copy JavaScript file to target");
    });
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

#[cfg(any(feature = "nfc", feature = "nfd", feature = "nfkc", feature = "nfkd"))]
extern crate unicode_normalization;
#[cfg(feature = "embed_all")] extern crate pocket_resources;

extern crate bincode;
extern crate fst;
extern crate hyphenation_commons;
extern crate serde;

use fst::Map;
use bincode as bin;
use serde::ser;
use std::collections::HashMap;
use std::hash::Hash;
use std::env;
use std::error;
use std::fmt;
use std::fs::{self, File};
use std::io;
use std::io::prelude::*;
use std::iter::{self, FromIterator};
use std::path::{Path, PathBuf};

use hyphenation_commons::dictionary::*;
use hyphenation_commons::dictionary::trie::Trie;
use hyphenation_commons::dictionary::extended as ext;
use hyphenation_commons::Language;
use hyphenation_commons::Language::*;
use hyphenation_commons::parse::*;

// Configuration of exclusive optional features

use configuration::*;
mod configuration {
    // In service of configurable normalization forms, a type alias and a function
    // are defined via conditional compilation.
    //
    // If no feature is explicitly set, normalization is avoided altogether.

    // Neither Cargo nor rustc allows us to set exclusive features; we must indulge
    // them with this clumsy branle of cfg declarations.
    #[cfg(not(any(feature = "nfc", feature = "nfd", feature = "nfkc", feature = "nfkd")))]
    pub fn normalize(s : &str) -> String { s.to_owned() }

    #[cfg(any(feature = "nfc", feature = "nfd", feature = "nfkc", feature = "nfkd"))]
    use unicode_normalization::*;

    #[cfg(feature = "nfc")]  pub fn normalize(s : &str) -> String { s.nfc().collect() }
    #[cfg(feature = "nfd")]  pub fn normalize(s : &str) -> String { s.nfd().collect() }
    #[cfg(feature = "nfkc")] pub fn normalize(s : &str) -> String { s.nfkc().collect() }
    #[cfg(feature = "nfkd")] pub fn normalize(s : &str) -> String { s.nfkd().collect() }
}

trait TryFromIterator<Tally> : Sized {
    fn try_from_iter<I>(iter : I) -> Result<Self, Error>
    where I : IntoIterator<Item = (String, Tally)>
            + ExactSizeIterator;
}

fn uniques<I, T>(iter : I) -> (Vec<(String, u64)>, Vec<T>)
where T : Eq + Clone + Hash
    , I : IntoIterator<Item = (String, T)>
        + ExactSizeIterator
{
    let mut pairs = Vec::with_capacity(iter.len());
    let mut tally_ids = HashMap::with_capacity(iter.len());
    let mut tallies : Vec<T> = Vec::with_capacity(256);
    for (pattern, tally) in iter {
        match tally_ids.get(&tally) {
            Some(&id) => pairs.push((pattern, id)),
            None => {
                let id = tallies.len() as u64;
                tallies.push(tally.clone());
                tally_ids.insert(tally, id);
                pairs.push((pattern, id));
            }
        }
    }
    pairs.sort_by(|a, b| a.0.cmp(&b.0));
    pairs.dedup_by(|a, b| a.0 == b.0);
    (pairs, tallies)
}

impl TryFromIterator<<Patterns as Parse>::Tally> for Patterns {
    fn try_from_iter<I>(iter : I) -> Result<Self, Error>
    where I : IntoIterator<Item = (String, <Patterns as Parse>::Tally)>
            + ExactSizeIterator
    {
        let (kvs, tallies) = uniques(iter);
        let map = Map::from_iter(kvs.into_iter()) ?;
        let automaton = Trie(map);
        Ok(Patterns { tallies, automaton })
    }
}

impl TryFromIterator<<Exceptions as Parse>::Tally> for Exceptions {
    fn try_from_iter<I>(iter : I) -> Result<Self, Error>
    where I : IntoIterator<Item = (String, <Exceptions as Parse>::Tally)>
            + ExactSizeIterator
    {
        Ok(Exceptions(HashMap::from_iter(iter)))
    }
}

impl TryFromIterator<<ext::Patterns as Parse>::Tally> for ext::Patterns {
    fn try_from_iter<I>(iter : I) -> Result<Self, Error>
    where I : IntoIterator<Item = (String, <ext::Patterns as Parse>::Tally)>
            + ExactSizeIterator
    {
        let (kvs, tallies) = uniques(iter);
        let map = Map::from_iter(kvs.into_iter()) ?;
        let automaton = Trie(map);
        Ok(ext::Patterns { tallies, automaton })
    }
}

// Dictionary building and serialization

#[derive(Clone, Debug)]
struct Paths {
    source : PathBuf,
    out : PathBuf
}

impl Paths {
    fn new() -> Result<Self, Error> {
        let source = env::var("CARGO_MANIFEST_DIR").map(|p| PathBuf::from(p)) ?;
        let out = env::var("OUT_DIR").map(|p| PathBuf::from(p)) ?;

        Ok(Paths { source, out })
    }

    fn destine_item<P : AsRef<Path>>(&self, p : P) -> PathBuf { self.out.join(p.as_ref()) }
    fn source_item<P : AsRef<Path>>(&self, p : P) -> PathBuf { self.source.join(p.as_ref()) }

    fn source_pattern(&self, lang : Language, suffix : &str) -> PathBuf {
        let fname = format!("hyph-{}.{}.txt", lang.code(), suffix);
        self.source_item("patterns").join(fname)
    }

    fn destine_dict(&self, lang : Language, suffix : &str) -> PathBuf {
        self.destine_item("dictionaries").join(Self::dict_name(lang, suffix))
    }

    fn dict_name(lang : Language, suffix : &str) -> String {
        format!("{}.{}.bincode", lang.code(), suffix)
    }
}

trait Build : Sized + Parse + TryFromIterator<<Self as Parse>::Tally> {
    fn suffix() -> &'static str;

    fn sourcepath(lang : Language, paths : &Paths) -> PathBuf {
        paths.source_pattern(lang, Self::suffix())
    }

    fn build(lang : Language, paths : &Paths) -> Result<Self, Error> {
        let file = File::open(Self::sourcepath(lang, paths)) ?;
        let by_line = io::BufReader::new(file).lines();
        let pairs : Vec<_> = by_line.map(|res| Self::pair(&res.unwrap(), normalize)).collect();

        Self::try_from_iter(pairs.into_iter())
    }
}

impl Build for Patterns   { fn suffix() -> &'static str { "pat" } }
impl Build for Exceptions { fn suffix() -> &'static str { "hyp" } }
impl Build for ext::Patterns { fn suffix() -> &'static str { "ext" } }

fn write<T>(item : &T, path : &Path) -> Result<(), Error> where T : ser::Serialize {
    let mut buffer = File::create(&path).map(|f| io::BufWriter::new(f)) ?;
    bin::config().limit(5_000_000).serialize_into(&mut buffer, item) ?;
    Ok(())
}

fn copy_dir(from : &Path, to : &Path) -> Result<(), Error> {
    for entry in fs::read_dir(from) ? {
        entry.and_then(|e| fs::copy(e.path(), to.join(e.file_name()))) ?;
    }

    Ok(())
}

// In which we cope with Cargo's criteria for rebuilding

fn lib_rebuildables() -> Vec<PathBuf> {
    vec![ Path::new("hyphenation_commons").join("src").join("dictionary.rs")
        , Path::new("src").join("load.rs") ]
}

fn demand_rebuild<P>(path : P) where P : AsRef<Path> {
    println!("cargo:rerun-if-changed={}", path.as_ref().display());
}

fn main() {
    let dict_folder = Path::new("dictionaries");
    let _std_out = "standard";
    let _ext_out = "extended";
    let paths = Paths::new().unwrap();
    let dict_source = paths.source_item(dict_folder);
    let dict_out = paths.destine_item(dict_folder);

    let ext_langs = vec![Catalan, Hungarian];
    let std_langs =
        vec![ Afrikaans, Armenian, Assamese, Basque, Belarusian, Bengali, Bulgarian, Catalan,
              Chinese, Coptic, Croatian, Czech, Danish, Dutch, EnglishGB, EnglishUS, Esperanto,
              Estonian, Ethiopic, Finnish, French, Friulan, Galician, Georgian, German1901,
              German1996, GermanSwiss, GreekAncient, GreekMono, GreekPoly, Gujarati, Hindi,
              Hungarian, Icelandic, Indonesian, Interlingua, Irish, Italian, Kannada, Kurmanji,
              Latin, LatinClassic, LatinLiturgical, Latvian, Lithuanian, Malayalam, Marathi,
              Mongolian, NorwegianBokmal, NorwegianNynorsk, Occitan, Oriya, Pali, Panjabi,
              Piedmontese, Polish, Portuguese, Romanian, Romansh, Russian, Sanskrit,
              SerbianCyrillic, SerbocroatianCyrillic, SerbocroatianLatin, SlavonicChurch, Slovak,
              Slovenian, Spanish, Swedish, Tamil, Telugu, Thai, Turkish, Turkmen, Ukrainian,
              Uppersorbian, Welsh ];

    fs::create_dir_all(&dict_out).unwrap();

    // If no dictionary is to be rebuilt, copy the bundled ones into the `target`
    // folder.
    #[cfg(not(any(feature = "build_dictionaries", feature = "nfc", feature = "nfd",
                  feature = "nfkc", feature = "nfkd")))]
    {
        copy_dir(dict_source.as_path(), dict_out.as_path()).unwrap();
    }

    // Otherwise, process the bundled patterns into new dictionaries and similarly
    // bundle them.
    #[cfg(any(feature = "build_dictionaries", feature = "nfc", feature = "nfd",
              feature = "nfkc", feature = "nfkd"))]
    {
        println!("Building `Standard` dictionaries:");
        for &language in std_langs.iter() {
            println!("  - {:?}", language);
            let dict = Standard {
                language,
                patterns : Patterns::build(language, &paths).unwrap(),
                exceptions : Exceptions::build(language, &paths).unwrap(),
                minima : language.minima()
            };

            write(&dict, &paths.destine_dict(language, _std_out)).unwrap();
        }

        println!("Building `Extended` dictionaries:");
        for &language in ext_langs.iter() {
            println!("  - {:?}", language);
            let dict = ext::Extended {
                language,
                patterns : ext::Patterns::build(language, &paths).unwrap(),
                exceptions : ext::Exceptions::default(),
                minima : language.minima()
            };

            write(&dict, &paths.destine_dict(language, _ext_out)).unwrap();
        }
    }

    #[cfg(all(feature = "embed_en-us", not(feature = "embed_all")))] {
        let dict = (&dict_folder, Paths::dict_name(EnglishUS, _std_out));
        pocket_resources::package(iter::once(&dict)).unwrap();
    }

    #[cfg(feature = "embed_all")] {
        // HEED: `pocket_resources` requires paths to be relative
        let std_p = std_langs.iter().map(|&l| (&dict_folder, Paths::dict_name(l, _std_out)));
        let ext_p = ext_langs.iter().map(|&l| (&dict_folder, Paths::dict_name(l, _ext_out)));
        let all_paths : Vec<_> = std_p.chain(ext_p).collect();
        pocket_resources::package(all_paths.iter()).unwrap();
    }

    // Specify which files will cause a rebuild if changed.

    for path in lib_rebuildables().iter() {
        demand_rebuild(&path);
    }

    for &lang in std_langs.iter() {
        demand_rebuild(Patterns::sourcepath(lang, &paths));
        demand_rebuild(Exceptions::sourcepath(lang, &paths));
    }
    for &lang in ext_langs.iter() {
        demand_rebuild(ext::Patterns::sourcepath(lang, &paths));
    }
}

// Error type boilerplate

#[derive(Debug)]
pub enum Error {
    Build(fst::Error),
    Env(env::VarError),
    IO(io::Error),
    Serialization(bin::Error),
    Resource
    // TODO: Parsing
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Build(ref e) => e.description(),
            Error::Env(ref e) => e.description(),
            Error::IO(ref e) => e.description(),
            Error::Serialization(ref e) => e.description(),
            Error::Resource => "pattern resource creation failed"
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Build(ref e) => e.fmt(f),
            Error::Env(ref e) => e.fmt(f),
            Error::IO(ref e) => e.fmt(f),
            Error::Serialization(ref e) => e.fmt(f),
            Error::Resource => {
                let e = self as &error::Error;
                e.description().fmt(f)
            }
        }
    }
}

impl From<io::Error> for Error {
    fn from(err : io::Error) -> Error { Error::IO(err) }
}

impl From<env::VarError> for Error {
    fn from(err : env::VarError) -> Error { Error::Env(err) }
}

impl From<bin::Error> for Error {
    fn from(err : bin::Error) -> Error { Error::Serialization(err) }
}

impl From<fst::Error> for Error {
    fn from(err : fst::Error) -> Error { Error::Build(err) }
}
<commit_msg>Avoid rebuilding unless requested or required by features<commit_after>#![allow(dead_code)]

#[cfg(any(feature = "nfc", feature = "nfd", feature = "nfkc", feature = "nfkd"))]
extern crate unicode_normalization;
#[cfg(feature = "embed_all")] extern crate pocket_resources;

extern crate bincode;
extern crate fst;
extern crate hyphenation_commons;
extern crate serde;

use fst::Map;
use bincode as bin;
use serde::ser;
use std::collections::HashMap;
use std::hash::Hash;
use std::env;
use std::error;
use std::fmt;
use std::fs::{self, File};
use std::io;
use std::io::prelude::*;
use std::iter::{self, FromIterator};
use std::path::{Path, PathBuf};

use hyphenation_commons::dictionary::*;
use hyphenation_commons::dictionary::trie::Trie;
use hyphenation_commons::dictionary::extended as ext;
use hyphenation_commons::Language;
use hyphenation_commons::Language::*;
use hyphenation_commons::parse::*;

// Configuration of exclusive optional features

use configuration::*;
mod configuration {
    // In service of configurable normalization forms, a type alias and a function
    // are defined via conditional compilation.
    //
    // If no feature is explicitly set, normalization is avoided altogether.

    // Neither Cargo nor rustc allows us to set exclusive features; we must indulge
    // them with this clumsy branle of cfg declarations.
    #[cfg(not(any(feature = "nfc", feature = "nfd", feature = "nfkc", feature = "nfkd")))]
    pub fn normalize(s : &str) -> String { s.to_owned() }

    #[cfg(any(feature = "nfc", feature = "nfd", feature = "nfkc", feature = "nfkd"))]
    use unicode_normalization::*;

    #[cfg(feature = "nfc")]  pub fn normalize(s : &str) -> String { s.nfc().collect() }
    #[cfg(feature = "nfd")]  pub fn normalize(s : &str) -> String { s.nfd().collect() }
    #[cfg(feature = "nfkc")] pub fn normalize(s : &str) -> String { s.nfkc().collect() }
    #[cfg(feature = "nfkd")] pub fn normalize(s : &str) -> String { s.nfkd().collect() }
}

trait TryFromIterator<Tally> : Sized {
    fn try_from_iter<I>(iter : I) -> Result<Self, Error>
    where I : IntoIterator<Item = (String, Tally)>
            + ExactSizeIterator;
}

fn uniques<I, T>(iter : I) -> (Vec<(String, u64)>, Vec<T>)
where T : Eq + Clone + Hash
    , I : IntoIterator<Item = (String, T)>
        + ExactSizeIterator
{
    let mut pairs = Vec::with_capacity(iter.len());
    let mut tally_ids = HashMap::with_capacity(iter.len());
    let mut tallies : Vec<T> = Vec::with_capacity(256);
    for (pattern, tally) in iter {
        match tally_ids.get(&tally) {
            Some(&id) => pairs.push((pattern, id)),
            None => {
                let id = tallies.len() as u64;
                tallies.push(tally.clone());
                tally_ids.insert(tally, id);
                pairs.push((pattern, id));
            }
        }
    }
    pairs.sort_by(|a, b| a.0.cmp(&b.0));
    pairs.dedup_by(|a, b| a.0 == b.0);
    (pairs, tallies)
}

impl TryFromIterator<<Patterns as Parse>::Tally> for Patterns {
    fn try_from_iter<I>(iter : I) -> Result<Self, Error>
    where I : IntoIterator<Item = (String, <Patterns as Parse>::Tally)>
            + ExactSizeIterator
    {
        let (kvs, tallies) = uniques(iter);
        let map = Map::from_iter(kvs.into_iter()) ?;
        let automaton = Trie(map);
        Ok(Patterns { tallies, automaton })
    }
}

impl TryFromIterator<<Exceptions as Parse>::Tally> for Exceptions {
    fn try_from_iter<I>(iter : I) -> Result<Self, Error>
    where I : IntoIterator<Item = (String, <Exceptions as Parse>::Tally)>
            + ExactSizeIterator
    {
        Ok(Exceptions(HashMap::from_iter(iter)))
    }
}

impl TryFromIterator<<ext::Patterns as Parse>::Tally> for ext::Patterns {
    fn try_from_iter<I>(iter : I) -> Result<Self, Error>
    where I : IntoIterator<Item = (String, <ext::Patterns as Parse>::Tally)>
            + ExactSizeIterator
    {
        let (kvs, tallies) = uniques(iter);
        let map = Map::from_iter(kvs.into_iter()) ?;
        let automaton = Trie(map);
        Ok(ext::Patterns { tallies, automaton })
    }
}

// Dictionary building and serialization

#[derive(Clone, Debug)]
struct Paths {
    source : PathBuf,
    out : PathBuf
}

impl Paths {
    fn new() -> Result<Self, Error> {
        let source = env::var("CARGO_MANIFEST_DIR").map(|p| PathBuf::from(p)) ?;
        let out = env::var("OUT_DIR").map(|p| PathBuf::from(p)) ?;

        Ok(Paths { source, out })
    }

    fn destine_item<P : AsRef<Path>>(&self, p : P) -> PathBuf { self.out.join(p.as_ref()) }
    fn source_item<P : AsRef<Path>>(&self, p : P) -> PathBuf { self.source.join(p.as_ref()) }

    fn source_pattern(&self, lang : Language, suffix : &str) -> PathBuf {
        let fname = format!("hyph-{}.{}.txt", lang.code(), suffix);
        self.source_item("patterns").join(fname)
    }

    fn destine_dict(&self, lang : Language, suffix : &str) -> PathBuf {
        self.destine_item("dictionaries").join(Self::dict_name(lang, suffix))
    }

    fn dict_name(lang : Language, suffix : &str) -> String {
        format!("{}.{}.bincode", lang.code(), suffix)
    }
}

trait Build : Sized + Parse + TryFromIterator<<Self as Parse>::Tally> {
    fn suffix() -> &'static str;

    fn sourcepath(lang : Language, paths : &Paths) -> PathBuf {
        paths.source_pattern(lang, Self::suffix())
    }

    fn build(lang : Language, paths : &Paths) -> Result<Self, Error> {
        let file = File::open(Self::sourcepath(lang, paths)) ?;
        let by_line = io::BufReader::new(file).lines();
        let pairs : Vec<_> = by_line.map(|res| Self::pair(&res.unwrap(), normalize)).collect();

        Self::try_from_iter(pairs.into_iter())
    }
}

impl Build for Patterns   { fn suffix() -> &'static str { "pat" } }
impl Build for Exceptions { fn suffix() -> &'static str { "hyp" } }
impl Build for ext::Patterns { fn suffix() -> &'static str { "ext" } }

fn write<T>(item : &T, path : &Path) -> Result<(), Error> where T : ser::Serialize {
    let mut buffer = File::create(&path).map(|f| io::BufWriter::new(f)) ?;
    bin::config().limit(5_000_000).serialize_into(&mut buffer, item) ?;
    Ok(())
}

fn copy_dir(from : &Path, to : &Path) -> Result<(), Error> {
    for entry in fs::read_dir(from) ? {
        entry.and_then(|e| fs::copy(e.path(), to.join(e.file_name()))) ?;
    }

    Ok(())
}

fn main() {
    let dict_folder = Path::new("dictionaries");
    let _std_out = "standard";
    let _ext_out = "extended";
    let paths = Paths::new().unwrap();
    let dict_source = paths.source_item(dict_folder);
    let dict_out = paths.destine_item(dict_folder);

    let ext_langs = vec![Catalan, Hungarian];
    let std_langs =
        vec![ Afrikaans, Armenian, Assamese, Basque, Belarusian, Bengali, Bulgarian, Catalan,
              Chinese, Coptic, Croatian, Czech, Danish, Dutch, EnglishGB, EnglishUS, Esperanto,
              Estonian, Ethiopic, Finnish, French, Friulan, Galician, Georgian, German1901,
              German1996, GermanSwiss, GreekAncient, GreekMono, GreekPoly, Gujarati, Hindi,
              Hungarian, Icelandic, Indonesian, Interlingua, Irish, Italian, Kannada, Kurmanji,
              Latin, LatinClassic, LatinLiturgical, Latvian, Lithuanian, Malayalam, Marathi,
              Mongolian, NorwegianBokmal, NorwegianNynorsk, Occitan, Oriya, Pali, Panjabi,
              Piedmontese, Polish, Portuguese, Romanian, Romansh, Russian, Sanskrit,
              SerbianCyrillic, SerbocroatianCyrillic, SerbocroatianLatin, SlavonicChurch, Slovak,
              Slovenian, Spanish, Swedish, Tamil, Telugu, Thai, Turkish, Turkmen, Ukrainian,
              Uppersorbian, Welsh ];

    fs::create_dir_all(&dict_out).unwrap();

    // If no dictionary is to be rebuilt, copy the bundled ones into the `target`
    // folder.
    #[cfg(not(any(feature = "build_dictionaries", feature = "nfc", feature = "nfd",
                  feature = "nfkc", feature = "nfkd")))]
    {
        copy_dir(dict_source.as_path(), dict_out.as_path()).unwrap();
    }

    // Otherwise, process the bundled patterns into new dictionaries and similarly
    // bundle them.
    #[cfg(any(feature = "build_dictionaries", feature = "nfc", feature = "nfd",
              feature = "nfkc", feature = "nfkd"))]
    {
        println!("Building `Standard` dictionaries:");
        for &language in std_langs.iter() {
            println!("  - {:?}", language);
            let dict = Standard {
                language,
                patterns : Patterns::build(language, &paths).unwrap(),
                exceptions : Exceptions::build(language, &paths).unwrap(),
                minima : language.minima()
            };

            write(&dict, &paths.destine_dict(language, _std_out)).unwrap();
        }

        println!("Building `Extended` dictionaries:");
        for &language in ext_langs.iter() {
            println!("  - {:?}", language);
            let dict = ext::Extended {
                language,
                patterns : ext::Patterns::build(language, &paths).unwrap(),
                exceptions : ext::Exceptions::default(),
                minima : language.minima()
            };

            write(&dict, &paths.destine_dict(language, _ext_out)).unwrap();
        }
    }

    #[cfg(all(feature = "embed_en-us", not(feature = "embed_all")))] {
        let dict = (&dict_folder, Paths::dict_name(EnglishUS, _std_out));
        pocket_resources::package(iter::once(&dict)).unwrap();
    }

    #[cfg(feature = "embed_all")] {
        // HEED: `pocket_resources` requires paths to be relative
        let std_p = std_langs.iter().map(|&l| (&dict_folder, Paths::dict_name(l, _std_out)));
        let ext_p = ext_langs.iter().map(|&l| (&dict_folder, Paths::dict_name(l, _ext_out)));
        let all_paths : Vec<_> = std_p.chain(ext_p).collect();
        pocket_resources::package(all_paths.iter()).unwrap();
    }

    println!("cargo:rerun-if-changed=build.rs");
}

// Error type boilerplate

#[derive(Debug)]
pub enum Error {
    Build(fst::Error),
    Env(env::VarError),
    IO(io::Error),
    Serialization(bin::Error),
    Resource
    // TODO: Parsing
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Build(ref e) => e.description(),
            Error::Env(ref e) => e.description(),
            Error::IO(ref e) => e.description(),
            Error::Serialization(ref e) => e.description(),
            Error::Resource => "pattern resource creation failed"
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Build(ref e) => e.fmt(f),
            Error::Env(ref e) => e.fmt(f),
            Error::IO(ref e) => e.fmt(f),
            Error::Serialization(ref e) => e.fmt(f),
            Error::Resource => {
                let e = self as &error::Error;
                e.description().fmt(f)
            }
        }
    }
}

impl From<io::Error> for Error {
    fn from(err : io::Error) -> Error { Error::IO(err) }
}

impl From<env::VarError> for Error {
    fn from(err : env::VarError) -> Error { Error::Env(err) }
}

impl From<bin::Error> for Error {
    fn from(err : bin::Error) -> Error { Error::Serialization(err) }
}

impl From<fst::Error> for Error {
    fn from(err : fst::Error) -> Error { Error::Build(err) }
}
<|endoftext|>


<commit_before>// build.rs

extern crate pkg_config;
extern crate bindgen;
extern crate cmake;
extern crate cc;

use std::env;
use std::path::Path;

use std::fs::OpenOptions;
use std::io::Write;

fn format_write(builder: bindgen::Builder, output: &str) {
    let s = builder
        .generate()
        .unwrap()
        .to_string()
        .replace("/**", "/*")
        .replace("/*!", "/*");

    let mut file = OpenOptions::new()
        .write(true)
        .truncate(true)
        .create(true)
        .open(output)
        .unwrap();

    let _ = file.write(s.as_bytes());
}

fn main() {
    let cargo_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let build_path = Path::new(&cargo_dir).join("aom_build/aom");

    let cfg = cmake::Config::new(build_path)
        .define("CONFIG_AV1_ENCODER", "0")
        .define("CONFIG_DEBUG", "1")
        .define("CONFIG_EXPERIMENTAL", "1")
        .define("CONFIG_UNIT_TESTS", "0")
        .define("CONFIG_AOM_QM", "0")
        .define("CONFIG_EXT_INTRA", "0")
        .define("CONFIG_EXT_PARTITION", "0")
        .define("CONFIG_EXT_PARTITION_TYPES", "0")
        .define("CONFIG_LOOPFILTER_LEVEL", "0")
        .define("CONFIG_INTRA_EDGE", "0")
        .define("CONFIG_CFL", "0")
        .define("CONFIG_KF_CTX", "0")
        .define("CONFIG_STRIPED_LOOP_RESTORATION", "0")
        .define("CONFIG_MAX_TILE", "0")
        .define("CONFIG_EXT_INTRA_MOD", "0")
        .define("CONFIG_FRAME_SIZE", "0")
        .define("CONFIG_Q_ADAPT_PROBS", "0")
        .define("CONFIG_SIMPLIFY_TX_MODE", "0")
        .define("CONFIG_OBU", "0")
        .define("CONFIG_FILTER_INTRA", "0")
        .define("CONFIG_ANALYZER", "0")
        .build();

    env::set_var("PKG_CONFIG_PATH", cfg.join("lib/pkgconfig"));

    let libs = pkg_config::Config::new().statik(true).probe("aom").unwrap();
    let headers = libs.include_paths.clone();

    let mut builder = bindgen::builder()
        .raw_line("#![allow(dead_code)]")
        .raw_line("#![allow(non_camel_case_types)]")
        .raw_line("#![allow(non_snake_case)]")
        .raw_line("#![allow(non_upper_case_globals)]")
        .blacklist_type("max_align_t")
        .header("data/aom.h");

    for header in headers {
        builder = builder.clang_arg("-I").clang_arg(header.to_str().unwrap());
    }

    // Manually fix the comment so rustdoc won't try to pick them
    format_write(builder, "tests/aom.rs");

    cc::Build::new()
        .file("aom_build/aom/aom_dsp/fwd_txfm.c")
        .file("aom_build/aom/av1/encoder/dct.c")
        .include("aom_build")
        .include("aom_build/aom")
        .flag("-std=c99")
        .compile("libntr.a");
}
<commit_msg>Use File::create instead of OpenOptions<commit_after>// build.rs

extern crate pkg_config;
extern crate bindgen;
extern crate cmake;
extern crate cc;

use std::env;
use std::path::Path;

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

fn format_write(builder: bindgen::Builder, output: &str) {
    let s = builder
        .generate()
        .unwrap()
        .to_string()
        .replace("/**", "/*")
        .replace("/*!", "/*");

    let mut file = File::create(output).unwrap();

    let _ = file.write(s.as_bytes());
}

fn main() {
    let cargo_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let build_path = Path::new(&cargo_dir).join("aom_build/aom");

    let cfg = cmake::Config::new(build_path)
        .define("CONFIG_AV1_ENCODER", "0")
        .define("CONFIG_DEBUG", "1")
        .define("CONFIG_EXPERIMENTAL", "1")
        .define("CONFIG_UNIT_TESTS", "0")
        .define("CONFIG_AOM_QM", "0")
        .define("CONFIG_EXT_INTRA", "0")
        .define("CONFIG_EXT_PARTITION", "0")
        .define("CONFIG_EXT_PARTITION_TYPES", "0")
        .define("CONFIG_LOOPFILTER_LEVEL", "0")
        .define("CONFIG_INTRA_EDGE", "0")
        .define("CONFIG_CFL", "0")
        .define("CONFIG_KF_CTX", "0")
        .define("CONFIG_STRIPED_LOOP_RESTORATION", "0")
        .define("CONFIG_MAX_TILE", "0")
        .define("CONFIG_EXT_INTRA_MOD", "0")
        .define("CONFIG_FRAME_SIZE", "0")
        .define("CONFIG_Q_ADAPT_PROBS", "0")
        .define("CONFIG_SIMPLIFY_TX_MODE", "0")
        .define("CONFIG_OBU", "0")
        .define("CONFIG_FILTER_INTRA", "0")
        .define("CONFIG_ANALYZER", "0")
        .build();

    env::set_var("PKG_CONFIG_PATH", cfg.join("lib/pkgconfig"));

    let libs = pkg_config::Config::new().statik(true).probe("aom").unwrap();
    let headers = libs.include_paths.clone();

    let mut builder = bindgen::builder()
        .raw_line("#![allow(dead_code)]")
        .raw_line("#![allow(non_camel_case_types)]")
        .raw_line("#![allow(non_snake_case)]")
        .raw_line("#![allow(non_upper_case_globals)]")
        .blacklist_type("max_align_t")
        .header("data/aom.h");

    for header in headers {
        builder = builder.clang_arg("-I").clang_arg(header.to_str().unwrap());
    }

    // Manually fix the comment so rustdoc won't try to pick them
    format_write(builder, "tests/aom.rs");

    cc::Build::new()
        .file("aom_build/aom/aom_dsp/fwd_txfm.c")
        .file("aom_build/aom/av1/encoder/dct.c")
        .include("aom_build")
        .include("aom_build/aom")
        .flag("-std=c99")
        .compile("libntr.a");
}
<|endoftext|>


<commit_before>#[cfg(feature = "serialization-protobuf")]
extern crate protoc_rust;

#[cfg(feature = "serialization-protobuf")]
fn assert_protobuf_version(version: &str) {
    use std::process::{Command, Stdio};
    let protoc = Command::new("protoc")
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .args(&["--version"])
        .spawn()
        .unwrap();
    let version_output = protoc.wait_with_output().unwrap();
    assert!(version_output.status.success());
    assert_eq!(
        String::from_utf8(version_output.stdout).unwrap().trim(),
        version.to_string().trim(),
        "protoc version must be 3.5.1"
    );
}

#[cfg(feature = "serialization-protobuf")]
fn build_protobuf(out_dir: &str, input: &[&str], includes: &[&str]) {
    use self::protoc_rust::{run, Args};
    run(Args {
        out_dir,
        input,
        includes,
        customize: Default::default(),
    }).expect("protoc");
}

#[cfg(feature = "serialization-protobuf")]
fn build_protobuf_schemata() {
    assert_protobuf_version(env!("PROTOC_VERSION"));
    build_protobuf("src/proto", &["protobuf/proof.proto"], &[]);
}

fn main() {
    #[cfg(feature = "serialization-protobuf")]
    build_protobuf_schemata();
}
<commit_msg>read protoc version pin instead of reading from env vars<commit_after>#[cfg(feature = "serialization-protobuf")]
extern crate protoc_rust;

#[cfg(feature = "serialization-protobuf")]
fn assert_protobuf_version(version: String) {
    use std::process::{Command, Stdio};
    let protoc = Command::new("protoc")
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .args(&["--version"])
        .spawn()
        .unwrap();
    let version_output = protoc.wait_with_output().unwrap();
    assert!(version_output.status.success());
    assert_eq!(
        String::from_utf8(version_output.stdout).unwrap().trim(),
        version.trim()
    );
}

#[cfg(feature = "serialization-protobuf")]
fn build_protobuf(out_dir: &str, input: &[&str], includes: &[&str]) {
    use self::protoc_rust::{run, Args};
    run(Args {
        out_dir,
        input,
        includes,
        customize: Default::default(),
    }).expect("protoc");
}

#[cfg(feature = "serialization-protobuf")]
fn build_protobuf_schemata() {
    use std::fs::File;
    use std::io::Read;
    let mut version_string = String::new();
    let mut version_pin =
        File::open("PROTOC_VERSION").expect("protoc version pin `PROTOC_VERSION` file is missing");
    version_pin.read_to_string(&mut version_string).expect("cannot read protoc pin file");
    assert_protobuf_version(version_string);
    build_protobuf("src/proto", &["protobuf/proof.proto"], &[]);
}

fn main() {
    #[cfg(feature = "serialization-protobuf")]
    build_protobuf_schemata();
}
<|endoftext|>


<commit_before>#![feature(convert)]

use std::process::{Command,Output};
use std::env;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::Write;

fn cmd_output_checked(c: &mut Command, msg: &str) -> Output
{
	let output = c.output().unwrap_or_else(|e| { panic!("{}: {}", msg, e); });
	if !output.status.success() { panic!("{}: {}", msg, String::from_utf8(output.stderr).unwrap()); }
	output
}

fn main()
{
	let base_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
	let base_path = Path::new(&base_dir);
	let o_dir = env::var("OUT_DIR").unwrap();
	let o_path = Path::new(&o_dir);

	let src_path = PathBuf::from(base_path.join("src"));
	let c99gen = PathBuf::from(o_path.join("c99-gen"));

	cmd_output_checked(Command::new("cmake").arg(src_path).current_dir(&o_path), "Failed to run CMake");
	cmd_output_checked(Command::new("make").current_dir(&o_path), "Failed to run make");

	let gen_out = cmd_output_checked(Command::new(c99gen).current_dir(&base_path), "Failed to run generator");
	let gen_path = PathBuf::from(o_path.join("gen.rs"));
	let mut gen_f = File::create(&gen_path).unwrap();

	gen_f.write_all(gen_out.stdout.as_slice()).unwrap();
}
<commit_msg>Fix: Unstable feature<commit_after>use std::process::{Command,Output};
use std::env;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::Write;

fn cmd_output_checked(c: &mut Command, msg: &str) -> Output
{
	let output = c.output().unwrap_or_else(|e| { panic!("{}: {}", msg, e); });
	if !output.status.success() { panic!("{}: {}", msg, String::from_utf8(output.stderr).unwrap()); }
	output
}

fn main()
{
	let base_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
	let base_path = Path::new(&base_dir);
	let o_dir = env::var("OUT_DIR").unwrap();
	let o_path = Path::new(&o_dir);

	let src_path = PathBuf::from(base_path.join("src"));
	let c99gen = PathBuf::from(o_path.join("c99-gen"));

	cmd_output_checked(Command::new("cmake").arg(src_path).current_dir(&o_path), "Failed to run CMake");
	cmd_output_checked(Command::new("make").current_dir(&o_path), "Failed to run make");

	let gen_out = cmd_output_checked(Command::new(c99gen).current_dir(&base_path), "Failed to run generator");
	let gen_path = PathBuf::from(o_path.join("gen.rs"));
	let mut gen_f = File::create(&gen_path).unwrap();

	gen_f.write_all(&*gen_out.stdout).unwrap();
}
<|endoftext|>


<commit_before>#![feature(core, exit_status, collections)]

extern crate "freetype" as ft;

use std::io::prelude::*;

use std::io::stderr;
use std::path::Path;
use std::env::{ args, set_exit_status };
use ft::ffi;

const WIDTH: usize = 32;
const HEIGHT: usize = 24;

fn draw_bitmap(bitmap: &ffi::FT_Bitmap, x: usize, y: usize) ->
    [[u8; WIDTH]; HEIGHT]
{
    let mut image = [[0u8; WIDTH]; HEIGHT];
    let mut p = 0;
    let mut q = 0;
    let x_max = x + bitmap.width as usize;
    let y_max = y + bitmap.rows as usize;

    for i in range(x, x_max) {
        for j in range(y, y_max) {
            if i >= WIDTH || j >= HEIGHT {
                continue;
            }

            unsafe {
                image[j][i] |= *bitmap.buffer.offset((q * bitmap.width + p) as isize);
            }
            q += 1;
        }
        q = 0;
        p += 1;
    }

    image
}

fn main() {
    let ref mut stderr = stderr();
    let ref mut args = args();
    if let (3, _) = args.size_hint() {}
    else {
        let exe = args.next().unwrap();
        let _ = writeln!(stderr, "Usage: {} font sample-text", exe);
        set_exit_status(1);
        return
    }

    let filename = args.nth(1).unwrap();
    let text = args.next().unwrap();

    let library = ft::Library::init().unwrap();
    let face = library.new_face(&Path::new(&filename), 0).unwrap();
    face.set_char_size(40 * 64, 0, 50, 0).unwrap();
    face.load_char(text.nfc_chars().next().unwrap() as usize, ft::face::RENDER).unwrap();

    let slot = face.glyph().raw();

    let x = slot.bitmap_left as usize;
    let y = HEIGHT - slot.bitmap_top as usize;
    let image = draw_bitmap(&slot.bitmap, x, y);

    for i in range(0, HEIGHT) {
        for j in range(0, WIDTH) {
            print!("{}", if image[i as usize][j as usize] == 0 {
                             " "
                         } else if image[i as usize][j as usize] < 128 {
                             "*"
                         } else {
                             "+"
                         });
        }
        println!("");
    }
}
<commit_msg>Fix range syntax and rustc features in examples<commit_after>#![feature(exit_status, unicode)]

extern crate "freetype" as ft;

use std::io::prelude::*;

use std::io::stderr;
use std::path::Path;
use std::env::{ args, set_exit_status };
use ft::ffi;

const WIDTH: usize = 32;
const HEIGHT: usize = 24;

fn draw_bitmap(bitmap: &ffi::FT_Bitmap, x: usize, y: usize) -> [[u8; WIDTH]; HEIGHT] {
    let mut image = [[0u8; WIDTH]; HEIGHT];
    let mut p = 0;
    let mut q = 0;
    let x_max = x + bitmap.width as usize;
    let y_max = y + bitmap.rows as usize;

    for i in x .. x_max {
        for j in y .. y_max {
            if i >= WIDTH || j >= HEIGHT {
                continue;
            }

            unsafe {
                image[j][i] |= *bitmap.buffer.offset((q * bitmap.width + p) as isize);
            }
            q += 1;
        }
        q = 0;
        p += 1;
    }

    image
}

fn main() {
    let ref mut stderr = stderr();
    let ref mut args = args();
    if let (3, _) = args.size_hint() {}
    else {
        let exe = args.next().unwrap();
        let _ = writeln!(stderr, "Usage: {} font sample-text", exe);
        set_exit_status(1);
        return
    }

    let filename = args.nth(1).unwrap();
    let text = args.next().unwrap();

    let library = ft::Library::init().unwrap();
    let face = library.new_face(&Path::new(&filename), 0).unwrap();
    face.set_char_size(40 * 64, 0, 50, 0).unwrap();
    face.load_char(text.nfc_chars().next().unwrap() as usize, ft::face::RENDER).unwrap();

    let slot = face.glyph().raw();

    let x = slot.bitmap_left as usize;
    let y = HEIGHT - slot.bitmap_top as usize;
    let image = draw_bitmap(&slot.bitmap, x, y);

    for i in 0 .. HEIGHT {
        for j in 0 .. WIDTH {
            print!("{}", if image[i as usize][j as usize] == 0 {
                             " "
                         } else if image[i as usize][j as usize] < 128 {
                             "*"
                         } else {
                             "+"
                         });
        }
        println!("");
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(all(feature = "serde_type"), feature(proc_macro))]

extern crate env_logger;
extern crate handlebars_iron as hbs;
extern crate iron;
extern crate router;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate maplit;
extern crate flate2;

use hbs::handlebars::{Context, Handlebars, Helper, Output, RenderContext, RenderError};
use hbs::{DirectorySource, HandlebarsEngine, MemorySource, Template};
use iron::headers::{ContentEncoding, Encoding};
use iron::prelude::*;
use iron::{status, AfterMiddleware};
use router::Router;

use flate2::write::GzEncoder;
use flate2::Compression;

mod data {
    use hbs::handlebars::to_json;
    use serde_json::value::{Map, Value};

    #[derive(Serialize, Debug)]
    pub struct Team {
        name: String,
        pts: u16,
    }

    pub fn make_data() -> Map<String, Value> {
        let mut data = Map::new();

        data.insert("year".to_string(), to_json(&"2015".to_owned()));

        let teams = vec![
            Team {
                name: "Jiangsu Sainty".to_string(),
                pts: 43u16,
            },
            Team {
                name: "Beijing Guoan".to_string(),
                pts: 27u16,
            },
            Team {
                name: "Guangzhou Evergrand".to_string(),
                pts: 22u16,
            },
            Team {
                name: "Shandong Luneng".to_string(),
                pts: 12u16,
            },
        ];

        data.insert("teams".to_string(), to_json(&teams));
        data.insert("engine".to_string(), to_json(&"serde_json".to_owned()));
        data
    }
}

use data::*;

/// the handlers
fn index(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::new("some/path/hello", data))
        .set_mut(status::Ok);
    Ok(resp)
}

fn memory(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::new("memory", data))
        .set_mut(status::Ok);
    Ok(resp)
}

fn temp(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::with(
        include_str!("templates/some/path/hello.hbs"),
        data,
    )).set_mut(status::Ok);
    Ok(resp)
}

fn plain(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "It works")))
}

// an example compression middleware
pub struct GzMiddleware;

impl AfterMiddleware for GzMiddleware {
    fn after(&self, _: &mut Request, mut resp: Response) -> IronResult<Response> {
        let compressed_bytes = resp.body.as_mut().map(|b| {
            let mut encoder = GzEncoder::new(Vec::new(), Compression::Best);
            {
                let _ = b.write_body(&mut encoder);
            }
            encoder.finish().unwrap()
        });

        if let Some(b) = compressed_bytes {
            resp.headers.set(ContentEncoding(vec![Encoding::Gzip]));
            resp.set_mut(b);
        }

        Ok(resp)
    }
}

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

    let mut hbse = HandlebarsEngine::new();

    // add a directory source, all files with .hbs suffix will be loaded as template
    hbse.add(Box::new(DirectorySource::new(
        "./examples/templates/",
        ".hbs",
    )));

    let mem_templates = btreemap! {
        "memory".to_owned() => include_str!("templates/some/path/hello.hbs").to_owned()
    };
    // add a memory based source
    hbse.add(Box::new(MemorySource(mem_templates)));

    // load templates from all registered sources
    if let Err(r) = hbse.reload() {
        panic!("{}", r);
    }

    hbse.handlebars_mut().register_helper(
        "some_helper",
        Box::new(
            |_: &Helper,
             _: &Handlebars,
             _: &Context,
             _: &mut RenderContext,
             _: &mut Output|
             -> Result<(), RenderError> { Ok(()) },
        ),
    );

    let mut router = Router::new();
    router
        .get("/", index, "index")
        .get("/mem", memory, "memory")
        .get("/temp", temp, "temp")
        .get("/plain", plain, "plain");
    let mut chain = Chain::new(router);
    chain.link_after(hbse);
    chain.link_after(GzMiddleware);
    println!("Server running at http://localhost:3000/");
    Iron::new(chain).http("localhost:3000").unwrap();
}
<commit_msg>(fix) remove unused cfg_attr<commit_after>extern crate env_logger;
extern crate handlebars_iron as hbs;
extern crate iron;
extern crate router;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate maplit;
extern crate flate2;

use hbs::handlebars::{Context, Handlebars, Helper, Output, RenderContext, RenderError};
use hbs::{DirectorySource, HandlebarsEngine, MemorySource, Template};
use iron::headers::{ContentEncoding, Encoding};
use iron::prelude::*;
use iron::{status, AfterMiddleware};
use router::Router;

use flate2::write::GzEncoder;
use flate2::Compression;

mod data {
    use hbs::handlebars::to_json;
    use serde_json::value::{Map, Value};

    #[derive(Serialize, Debug)]
    pub struct Team {
        name: String,
        pts: u16,
    }

    pub fn make_data() -> Map<String, Value> {
        let mut data = Map::new();

        data.insert("year".to_string(), to_json(&"2015".to_owned()));

        let teams = vec![
            Team {
                name: "Jiangsu Sainty".to_string(),
                pts: 43u16,
            },
            Team {
                name: "Beijing Guoan".to_string(),
                pts: 27u16,
            },
            Team {
                name: "Guangzhou Evergrand".to_string(),
                pts: 22u16,
            },
            Team {
                name: "Shandong Luneng".to_string(),
                pts: 12u16,
            },
        ];

        data.insert("teams".to_string(), to_json(&teams));
        data.insert("engine".to_string(), to_json(&"serde_json".to_owned()));
        data
    }
}

use data::*;

/// the handlers
fn index(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::new("some/path/hello", data))
        .set_mut(status::Ok);
    Ok(resp)
}

fn memory(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::new("memory", data))
        .set_mut(status::Ok);
    Ok(resp)
}

fn temp(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::with(
        include_str!("templates/some/path/hello.hbs"),
        data,
    )).set_mut(status::Ok);
    Ok(resp)
}

fn plain(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "It works")))
}

// an example compression middleware
pub struct GzMiddleware;

impl AfterMiddleware for GzMiddleware {
    fn after(&self, _: &mut Request, mut resp: Response) -> IronResult<Response> {
        let compressed_bytes = resp.body.as_mut().map(|b| {
            let mut encoder = GzEncoder::new(Vec::new(), Compression::Best);
            {
                let _ = b.write_body(&mut encoder);
            }
            encoder.finish().unwrap()
        });

        if let Some(b) = compressed_bytes {
            resp.headers.set(ContentEncoding(vec![Encoding::Gzip]));
            resp.set_mut(b);
        }

        Ok(resp)
    }
}

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

    let mut hbse = HandlebarsEngine::new();

    // add a directory source, all files with .hbs suffix will be loaded as template
    hbse.add(Box::new(DirectorySource::new(
        "./examples/templates/",
        ".hbs",
    )));

    let mem_templates = btreemap! {
        "memory".to_owned() => include_str!("templates/some/path/hello.hbs").to_owned()
    };
    // add a memory based source
    hbse.add(Box::new(MemorySource(mem_templates)));

    // load templates from all registered sources
    if let Err(r) = hbse.reload() {
        panic!("{}", r);
    }

    hbse.handlebars_mut().register_helper(
        "some_helper",
        Box::new(
            |_: &Helper,
             _: &Handlebars,
             _: &Context,
             _: &mut RenderContext,
             _: &mut Output|
             -> Result<(), RenderError> { Ok(()) },
        ),
    );

    let mut router = Router::new();
    router
        .get("/", index, "index")
        .get("/mem", memory, "memory")
        .get("/temp", temp, "temp")
        .get("/plain", plain, "plain");
    let mut chain = Chain::new(router);
    chain.link_after(hbse);
    chain.link_after(GzMiddleware);
    println!("Server running at http://localhost:3000/");
    Iron::new(chain).http("localhost:3000").unwrap();
}
<|endoftext|>


<commit_before>extern crate gcc;
extern crate libbindgen;

use std::env;
use std::path::Path;

fn main() {
    let mut gcc_config = gcc::Config::new();

    gcc_config.file("src/fasthash.cpp")
        .file("src/smhasher/City.cpp")
        .file("src/smhasher/farmhash-c.c")
        .file("src/smhasher/lookup3.cpp")
        .file("src/smhasher/mum.cc")
        .file("src/smhasher/metrohash64.cpp")
        .file("src/smhasher/metrohash128.cpp")
        .file("src/smhasher/MurmurHash1.cpp")
        .file("src/smhasher/MurmurHash2.cpp")
        .file("src/smhasher/MurmurHash3.cpp")
        .file("src/smhasher/Spooky.cpp")
        .file("src/smhasher/t1ha.cc")
        .file("src/smhasher/xxhash.c");

    if cfg!(feature = "sse42") {
        gcc_config.flag("-msse4.2")
            .file("src/smhasher/metrohash64crc.cpp")
            .file("src/smhasher/metrohash128crc.cpp");
    }

    gcc_config.compile("libfasthash.a");

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_file = Path::new(&out_dir).join("src/fasthash.rs");

    if Path::new("src/fasthash.rs").exists() {
        std::fs::copy("src/fasthash.rs", out_file).unwrap();

        println!("cargo:rustc-link-lib=static=fasthash");
    } else {
        let _ = libbindgen::builder()
            .clang_arg("-xc++")
            .clang_arg("--std=c++11")
            .clang_arg(if cfg!(feature = "sse42") {
                "-msse4.2"
            } else {
                "-march=native"
            })
            .header("src/fasthash.hpp")
            .no_unstable_rust()
            .whitelisted_function("^CityHash.*")
            .whitelisted_function("^farmhash.*")
            .whitelisted_function("^lookup3.*")
            .whitelisted_function("^metrohash.*")
            .whitelisted_function("^mum_hash.*")
            .whitelisted_function("^MurmurHash.*")
            .whitelisted_function("^SpookyHasher.*")
            .whitelisted_function("^t1ha.*")
            .whitelisted_function("^XXH.*")
            .link_static("fasthash")
            .generate()
            .unwrap()
            .write_to_file(out_file)
            .expect("Couldn't write bindings!");
    }

    if cfg!(target_os = "macos") {
        println!("cargo:rustc-link-lib=dylib=c++");
    } else {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    }
}
<commit_msg>Copy generated file back to src<commit_after>extern crate gcc;
extern crate libbindgen;

use std::env;
use std::path::Path;

fn main() {
    let mut gcc_config = gcc::Config::new();

    gcc_config.file("src/fasthash.cpp")
        .file("src/smhasher/City.cpp")
        .file("src/smhasher/farmhash-c.c")
        .file("src/smhasher/lookup3.cpp")
        .file("src/smhasher/mum.cc")
        .file("src/smhasher/metrohash64.cpp")
        .file("src/smhasher/metrohash128.cpp")
        .file("src/smhasher/MurmurHash1.cpp")
        .file("src/smhasher/MurmurHash2.cpp")
        .file("src/smhasher/MurmurHash3.cpp")
        .file("src/smhasher/Spooky.cpp")
        .file("src/smhasher/t1ha.cc")
        .file("src/smhasher/xxhash.c");

    if cfg!(feature = "sse42") {
        gcc_config.flag("-msse4.2")
            .file("src/smhasher/metrohash64crc.cpp")
            .file("src/smhasher/metrohash128crc.cpp");
    }

    gcc_config.compile("libfasthash.a");

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_file = Path::new(&out_dir).join("src/fasthash.rs");

    if Path::new("src/fasthash.rs").exists() {
        std::fs::copy("src/fasthash.rs", out_file).unwrap();

        println!("cargo:rustc-link-lib=static=fasthash");
    } else {
        let _ = libbindgen::builder()
            .clang_arg("-xc++")
            .clang_arg("--std=c++11")
            .clang_arg(if cfg!(feature = "sse42") {
                "-msse4.2"
            } else {
                "-march=native"
            })
            .header("src/fasthash.hpp")
            .no_unstable_rust()
            .whitelisted_function("^CityHash.*")
            .whitelisted_function("^farmhash.*")
            .whitelisted_function("^lookup3.*")
            .whitelisted_function("^metrohash.*")
            .whitelisted_function("^mum_hash.*")
            .whitelisted_function("^MurmurHash.*")
            .whitelisted_function("^SpookyHasher.*")
            .whitelisted_function("^t1ha.*")
            .whitelisted_function("^XXH.*")
            .link_static("fasthash")
            .generate()
            .unwrap()
            .write_to_file(out_file)
            .expect("Couldn't write bindings!");

        std::fs::copy(out_file, "src/fasthash.rs").unwrap();
    }

    if cfg!(target_os = "macos") {
        println!("cargo:rustc-link-lib=dylib=c++");
    } else {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    }
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

#[macro_use]
mod commands;

use std::env;

use commands::{streaminfo, comments, seektable, picture};
use docopt::Docopt;

const USAGE: &'static str = "
Usage: metadata <command> [<args>...]
       metadata [options]

Options:
  -h, --help  Show this message.

Commands:
  streaminfo  Display stream information.
  comments    Display or export comment tags.
  seektable   Display seek table.
  picture     Export picutes.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_command: Option<Command>,
  arg_args: Vec<String>,
}

#[derive(Clone, Copy, Debug, RustcDecodable)]
enum Command {
  StreamInfo,
  Comments,
  SeekTable,
  Picture,
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.options_first(true).decode())
    .unwrap_or_else(|e| e.exit());

  match args.arg_command.unwrap() {
    Command::StreamInfo => {
      let sub_args: streaminfo::Arguments = Docopt::new(streaminfo::USAGE)
        .and_then(|d| d.argv(env::args()).decode())
        .unwrap_or_else(|e| e.exit());

      streaminfo::run(&sub_args)
    }
    Command::Comments   => {
      let sub_args: comments::Arguments = Docopt::new(comments::USAGE)
        .and_then(|d| d.argv(env::args()).decode())
        .unwrap_or_else(|e| e.exit());

      comments::run(&sub_args)
    }
    Command::SeekTable  => {
      let sub_args: seektable::Arguments = Docopt::new(seektable::USAGE)
        .and_then(|d| d.argv(env::args()).decode())
        .unwrap_or_else(|e| e.exit());

      seektable::run(&sub_args)
    }
    Command::Picture    => {
      let sub_args: picture::Arguments = Docopt::new(picture::USAGE)
        .and_then(|d| d.argv(env::args()).decode())
        .unwrap_or_else(|e| e.exit());

      picture::run(&sub_args)
    }
  }
}
<commit_msg>Move subcommand handling to a seperate function<commit_after>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

#[macro_use]
mod commands;

use std::env;

use commands::{streaminfo, comments, seektable, picture};
use docopt::Docopt;

const USAGE: &'static str = "
Usage: metadata <command> [<args>...]
       metadata [options]

Options:
  -h, --help  Show this message.

Commands:
  streaminfo  Display stream information.
  comments    Display or export comment tags.
  seektable   Display seek table.
  picture     Export picutes.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_command: Option<Command>,
  arg_args: Vec<String>,
}

#[derive(Clone, Copy, Debug, RustcDecodable)]
enum Command {
  StreamInfo,
  Comments,
  SeekTable,
  Picture,
}

fn handle_subcommand(command: Command) {
  match command {
    Command::StreamInfo => {
      let sub_args: streaminfo::Arguments = Docopt::new(streaminfo::USAGE)
        .and_then(|d| d.argv(env::args()).decode())
        .unwrap_or_else(|e| e.exit());

      streaminfo::run(&sub_args)
    }
    Command::Comments   => {
      let sub_args: comments::Arguments = Docopt::new(comments::USAGE)
        .and_then(|d| d.argv(env::args()).decode())
        .unwrap_or_else(|e| e.exit());

      comments::run(&sub_args)
    }
    Command::SeekTable  => {
      let sub_args: seektable::Arguments = Docopt::new(seektable::USAGE)
        .and_then(|d| d.argv(env::args()).decode())
        .unwrap_or_else(|e| e.exit());

      seektable::run(&sub_args)
    }
    Command::Picture    => {
      let sub_args: picture::Arguments = Docopt::new(picture::USAGE)
        .and_then(|d| d.argv(env::args()).decode())
        .unwrap_or_else(|e| e.exit());

      picture::run(&sub_args)
    }
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.options_first(true).decode())
    .unwrap_or_else(|e| e.exit());

  handle_subcommand(args.arg_command.unwrap());
}
<|endoftext|>


<commit_before>//! Download and print the Rust homepage.
//!
//! This is the [Hello, World!] example from the [futures tutorial] extended
//! to use our resolver.
//!
//! [Hello, World!]: https://github.com/alexcrichton/futures-rs/blob/master/TUTORIAL.md#hello-world
//! [futures tutorial]: https://github.com/alexcrichton/futures-rs/blob/master/TUTORIAL.md

extern crate futures;
extern crate tokio_core;
//extern crate tokio_tls;
extern crate domain;

use std::str::FromStr;

use futures::Future;
use tokio_core::reactor::Core;
use tokio_core::net::TcpStream;
//use tokio_tls::ClientContext;
use domain::bits::DNameBuf;
use domain::resolv::Resolver;
use domain::resolv::lookup::lookup_host;

#[allow(unknown_lints, string_lit_as_bytes)]
fn main() {
    let mut core = Core::new().unwrap();

    let resolver = Resolver::new(&core.handle());
    let addr = lookup_host(resolver, DNameBuf::from_str("www.rust-lang.org")
                                              .unwrap()).map_err(Into::into);

    let socket_handle = core.handle();
    let socket = addr.and_then(|addr| {
        TcpStream::connect(&addr.port_iter(80).next().unwrap(),
        //TcpStream::connect(&addr.port_iter(443).next().unwrap(),
                           &socket_handle)
    });

    /*
    let tls_handshake = socket.and_then(|socket| {
        let cx = ClientContext::new().unwrap();
        cx.handshake("www.rust-lang.org", socket)
    });
    let request = tls_handshake.and_then(|socket| {
    */
    let request = socket.and_then(|socket| {
        tokio_core::io::write_all(socket, "\
            GET / HTTP/1.0\r\n\
            Host: www.rust-lang.org\r\n\
            \r\n\
        ".as_bytes())
    });
    let response = request.and_then(|(socket, _)| {
        tokio_core::io::read_to_end(socket, Vec::new())
    });

    let (_, data) = core.run(response).unwrap();
    println!("{}", String::from_utf8_lossy(&data));
}
<commit_msg>Update rusthome example.<commit_after>//! Download and print the Rust homepage.
//!
//! This is the [toy HTTP+TLS client] example from the [futures tutorial]
//! extended to use our resolver.
//!
//! [toy HTTP+TLS client]: https://tokio.rs/docs/getting-started/tls/
//! [futures tutorial]: https://tokio.rs/docs/getting-started/futures/

extern crate futures;
extern crate native_tls;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_tls;
extern crate domain;

use std::io;
use std::str::FromStr;

use futures::Future;
use native_tls::TlsConnector;
use tokio_core::net::TcpStream;
use tokio_core::reactor::Core;
use tokio_tls::TlsConnectorExt;
use domain::bits::DNameBuf;
use domain::resolv::Resolver;
use domain::resolv::lookup::lookup_host;

#[allow(unknown_lints, string_lit_as_bytes)]
fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let resolver = Resolver::new(&handle);
    let addr = lookup_host(resolver, DNameBuf::from_str("www.rust-lang.org")
                                              .unwrap()).map_err(Into::into);
    let cx = TlsConnector::builder().unwrap().build().unwrap();
    let socket = addr.and_then(|addr| {
        TcpStream::connect(&addr.port_iter(443).next().unwrap(), &handle)
    });

    let tls_handshake = socket.and_then(|socket| {
        let tls = cx.connect_async("www.rust-lang.org", socket);
        tls.map_err(|e| {
            io::Error::new(io::ErrorKind::Other, e)
        })
    });
    let request = tls_handshake.and_then(|socket| {
        tokio_io::io::write_all(socket, "\
            GET / HTTP/1.0\r\n\
            Host: www.rust-lang.org\r\n\
            \r\n\
        ".as_bytes())
    });
    let response = request.and_then(|(socket, _request)| {
        tokio_io::io::read_to_end(socket, Vec::new())
    });

    let (_socket, data) = core.run(response).unwrap();
    println!("{}", String::from_utf8_lossy(&data));
}
<|endoftext|>


<commit_before>use super::io_error;
use crate::{
    Connection, Result, Session, SessionManager,
    errors::Error,
};
use r2d2;
use std::net::TcpStream;

impl r2d2::ManageConnection for SessionManager {
    type Connection = Session;
    type Error = Error;

    fn connect(&self) -> Result<Session> {
        Session::new(self.0)
    }

    fn is_valid(&self, conn: &mut Session) -> Result<()> {
        conn.is_valid()
    }

    fn has_broken(&self, conn: &mut Session) -> bool {
        conn.broken
    }
}

impl Session {
    fn new(conn: Connection) -> Result<Session> {
        let cfg = conn.config();
        let mut servers: Vec<_> = cfg.cluster.values().collect();
        servers.sort();
        log::debug!("cluster: {:?}", servers);

        for server in servers {
            for address in server.addresses.iter() {
                log::debug!("connecting to {}", address);
                match TcpStream::connect(&address) {
                    Ok(stream) => {
                        let mut conn = Session {
                            id: 0,
                            broken: false,
                            stream: stream,
                        };

                        conn.handshake(&cfg.opts)?;
                        log::debug!("connected successfully");
                        return Ok(conn);
                    }
                    Err(error) => {
                        log::warn!("failed to connect to {}: {}", address, error);
                        conn.set_latency()?;
                        if let Ok(session) = Self::new(conn) {
                            return Ok(session);
                        }
                    }
                }
            }
        }

        Err(io_error("failed to connect to any server"))?
    }
}
<commit_msg>fix stack overflow when servers are offline<commit_after>use super::io_error;
use crate::{
    Connection, Result, Session, SessionManager,
    errors::Error,
};
use r2d2;
use std::net::TcpStream;

impl r2d2::ManageConnection for SessionManager {
    type Connection = Session;
    type Error = Error;

    fn connect(&self) -> Result<Session> {
        Session::new(self.0)
    }

    fn is_valid(&self, conn: &mut Session) -> Result<()> {
        conn.is_valid()
    }

    fn has_broken(&self, conn: &mut Session) -> bool {
        conn.broken
    }
}

impl Session {
    fn new(conn: Connection) -> Result<Session> {
        let cfg = conn.config();
        let mut servers: Vec<_> = cfg.cluster.values().collect();
        servers.sort();
        log::debug!("cluster: {:?}", servers);

        for server in servers {
            for address in server.addresses.iter() {
                log::debug!("connecting to {}", address);
                match TcpStream::connect(&address) {
                    Ok(stream) => {
                        let mut conn = Session {
                            id: 0,
                            broken: false,
                            stream: stream,
                        };

                        conn.handshake(&cfg.opts)?;
                        log::debug!("connected successfully");
                        return Ok(conn);
                    }
                    Err(error) => {
                        log::warn!("failed to connect to {}: {}", address, error);
                        conn.set_latency()?;
                        continue;
                    }
                }
            }
        }

        Err(io_error("failed to connect to any server"))?
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::path::{Path, PathBuf};

use rrg::session::Sink;
use structopt::StructOpt;

#[derive(StructOpt)]
#[structopt(name = "timeline", about = "A binary for the timeline action.")]
struct Opts {
    #[structopt(long="root", name="FILE", default_value="/",
                help="A path to the root directory to timeline.")]
    root: PathBuf,

    #[structopt(long="output", about="FILE",
                help="A path to a file to dump the results into.")]
    output: PathBuf,
}

struct Session {
    output: File,
}

impl Session {

    fn open<P: AsRef<Path>>(output: P) -> Session {
        let output = File::create(output)
            .expect("failed to create the output file");

        Session {
            output: output,
        }
    }
}

impl rrg::session::Session for Session {

    fn reply<R>(&mut self, response: R) -> rrg::session::Result<()>
    where
        R: rrg::action::Response + 'static,
    {
        // We don't care about the chunk ids.
        drop(response);
        Ok(())
    }

    fn send<R>(&mut self, sink: Sink, response: R) -> rrg::session::Result<()>
    where
        R: rrg::action::Response + 'static,
    {
        use std::io::Write as _;
        use byteorder::{BigEndian, WriteBytesExt as _};

        assert_eq!(sink, Sink::TRANSFER_STORE);

        let response = (&response as &dyn std::any::Any)
            .downcast_ref::<rrg::action::timeline::Chunk>()
            .expect("unexpected response type");

        self.output.write_u64::<BigEndian>(response.data.len() as u64)
            .expect("failed to write chunk size tag");
        self.output.write_all(&response.data[..])
            .expect("failed to write chunk data");

        Ok(())
    }
}

fn main() {
    let opts = Opts::from_args();

    let mut session = Session::open(opts.output);

    let request = rrg::action::timeline::Request {
        root: opts.root,
    };

    rrg::action::timeline::handle(&mut session, request)
        .expect("failed to execute the action");
}
<commit_msg>Write documentation for the timelining example.<commit_after>//! An example that timelines the specified folder.
//!
//! The timeline action is one of the filesystem tools that the GRR agent
//! exposes. Its description is pretty simple: given a folder, it returns a
//! stream of stat entries for all the files in it (including all subfolders).
//!
//! This example is a tiny wrapper around this action that allows to execute it
//! as a standalone binary without all the RRG setup required. A primary reason
//! for creating it is to compare the efficiency Rust implementation against the
//! existing Python one.

use std::fs::File;
use std::path::{Path, PathBuf};

use rrg::session::Sink;
use structopt::StructOpt;

/// A type for the timelining example command-line arguments.
#[derive(StructOpt)]
#[structopt(name = "timeline", about = "A binary for the timeline action.")]
struct Opts {
    /// A path to the root directory to timeline.
    #[structopt(long="root", name="FILE", default_value="/",
                help="A path to the root directory to timeline.")]
    root: PathBuf,

    /// A path to a file to dump the results into.
    #[structopt(long="output", about="FILE",
                help="A path to a file to dump the results into.")]
    output: PathBuf,
}

/// A session type of the timeline example.
///
/// Every action handler needs a session object. "Real" sessions handle comms
/// with the GRR server, error reporting and alike. However, this is not needed
/// here and the example session simply dumps everything into the specified file
/// encoding data in the gzchunked format.
struct Session {
    /// A file into which the data chunks of the output are dumped.
    output: File,
}

impl Session {

    /// Creates a session object that will write to the given `output` path.
    fn open<P: AsRef<Path>>(output: P) -> Session {
        let output = File::create(output)
            .expect("failed to create the output file");

        Session {
            output: output,
        }
    }
}

impl rrg::session::Session for Session {

    fn reply<R>(&mut self, response: R) -> rrg::session::Result<()>
    where
        R: rrg::action::Response + 'static,
    {
        // We don't care about the chunk ids.
        drop(response);
        Ok(())
    }

    fn send<R>(&mut self, sink: Sink, response: R) -> rrg::session::Result<()>
    where
        R: rrg::action::Response + 'static,
    {
        use std::io::Write as _;
        use byteorder::{BigEndian, WriteBytesExt as _};

        assert_eq!(sink, Sink::TRANSFER_STORE);

        let response = (&response as &dyn std::any::Any)
            .downcast_ref::<rrg::action::timeline::Chunk>()
            .expect("unexpected response type");

        self.output.write_u64::<BigEndian>(response.data.len() as u64)
            .expect("failed to write chunk size tag");
        self.output.write_all(&response.data[..])
            .expect("failed to write chunk data");

        Ok(())
    }
}

fn main() {
    let opts = Opts::from_args();

    let mut session = Session::open(opts.output);

    let request = rrg::action::timeline::Request {
        root: opts.root,
    };

    rrg::action::timeline::handle(&mut session, request)
        .expect("failed to execute the action");
}
<|endoftext|>


<commit_before>//! An example that uses CPUID to determine the system topology.
//!
//! Intel Topology is a pretty complicated subject (unfortunately):
//! https://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/
extern crate core_affinity;
extern crate raw_cpuid;

use raw_cpuid::{CpuId, ExtendedTopologyLevel, TopologyType};
use std::thread;

/// Runs CPU ID on every core in the system (to gather all APIC IDs).
///
/// # Note
/// This won't work on macOS, apparently there is no guarantee after setting the affinity
/// that a thread will really execute on the pinned core.
fn gather_all_xapic_ids() -> Vec<u8> {
    let core_ids = core_affinity::get_core_ids().unwrap();

    // Create a thread for each active CPU core.
    core_ids
        .into_iter()
        .map(|id| {
            thread::spawn(move || {
                // Pin this thread to a single CPU core.
                core_affinity::set_for_current(id);
                // Do more work after this.
                let cpuid = CpuId::new();
                cpuid
                    .get_feature_info()
                    .map_or_else(|| 0, |finfo| finfo.initial_local_apic_id())
            })
            .join()
            .unwrap_or(0)
        })
        .collect::<Vec<_>>()
}

/// Runs CPU ID on every core in the system (to gather all x2APIC IDs).
///
/// # Note
/// This won't work on macOS, apparently there is no guarantee after setting the affinity
/// that a thread will really execute on the pinned core.
fn gather_all_x2apic_ids() -> Vec<u32> {
    let core_ids = core_affinity::get_core_ids().unwrap();

    // Create a thread for each active CPU core.
    core_ids
        .into_iter()
        .map(|id| {
            thread::spawn(move || {
                // Pin this thread to a single CPU core.
                core_affinity::set_for_current(id);
                // Do more work after this.
                let cpuid = CpuId::new();
                cpuid.get_extended_topology_info().map_or_else(
                    || 0,
                    |mut topiter| topiter.next().as_ref().unwrap().x2apic_id(),
                )
            })
            .join()
            .unwrap_or(0)
        })
        .collect::<Vec<_>>()
}

fn enumerate_with_extended_topology_info() {
    let cpuid = CpuId::new();
    let mut smt_x2apic_shift: u32 = 0;
    let mut core_x2apic_shift: u32 = 0;

    cpuid.get_extended_topology_info().map_or_else(
        || println!("No topology information available."),
        |topoiter| {
            let topology: Vec<ExtendedTopologyLevel> = topoiter.collect();
            for topolevel in topology.iter() {
                match topolevel.level_type() {
                    TopologyType::SMT => {
                        smt_x2apic_shift = topolevel.shift_right_for_next_apic_id();
                    }
                    TopologyType::Core => {
                        core_x2apic_shift = topolevel.shift_right_for_next_apic_id();
                    }
                    _ => panic!("Topology category not supported."),
                };
            }
        },
    );

    println!("Enumeration of all cores in the system (with x2APIC IDs):");
    let mut all_x2apic_ids: Vec<u32> = gather_all_x2apic_ids();
    all_x2apic_ids.sort_unstable();
    for x2apic_id in all_x2apic_ids {
        let smt_select_mask = !(u32::max_value() << smt_x2apic_shift);
        let core_select_mask = (!((u32::max_value()) << core_x2apic_shift)) ^ smt_select_mask;
        let pkg_select_mask = u32::max_value() << core_x2apic_shift;

        let smt_id = x2apic_id & smt_select_mask;
        let core_id = (x2apic_id & core_select_mask) >> smt_x2apic_shift;
        let pkg_id = (x2apic_id & pkg_select_mask) >> core_x2apic_shift;

        println!(
            "x2APIC#{} (pkg: {}, core: {}, smt: {})",
            x2apic_id, pkg_id, core_id, smt_id
        );
    }
}

fn cpuid_bits_needed(count: u8) -> u8 {
    let mut mask: u8 = 0x80;
    let mut cnt: u8 = 8;

    while (cnt > 0) && ((mask & count) != mask) {
        mask >>= 1;
        cnt -= 1;
    }

    cnt
}

fn enumerate_with_legacy_leaf_1_4() {
    let cpuid = CpuId::new();
    let max_logical_processor_ids = cpuid
        .get_feature_info()
        .map_or_else(|| 0, |finfo| finfo.max_logical_processor_ids());

    let mut smt_max_cores_for_package: u8 = 0;
    cpuid.get_cache_parameters().map_or_else(
        || println!("No cache parameter information available"),
        |cparams| {
            for (ecx, cache) in cparams.enumerate() {
                if ecx == 0 {
                    smt_max_cores_for_package = cache.max_cores_for_package() as u8;
                }
            }
        },
    );

    let smt_mask_width: u8 = cpuid_bits_needed(
        (max_logical_processor_ids.next_power_of_two() / smt_max_cores_for_package) - 1,
    );
    let smt_select_mask: u8 = !(u8::max_value() << smt_mask_width);
    let core_mask_width: u8 = cpuid_bits_needed(smt_max_cores_for_package - 1);
    let core_only_select_mask =
        (!(u8::max_value() << (core_mask_width + smt_mask_width))) ^ smt_select_mask;
    let pkg_select_mask = u8::max_value() << (core_mask_width + smt_mask_width);

    println!("Enumeration of all cores in the system (with APIC IDs):");
    let mut all_xapic_ids: Vec<u8> = gather_all_xapic_ids();
    all_xapic_ids.sort_unstable();

    for xapic_id in all_xapic_ids {
        let smt_id = xapic_id & smt_select_mask;
        let core_id = (xapic_id & core_only_select_mask) >> smt_mask_width;
        let pkg_id = (xapic_id & pkg_select_mask) >> (core_mask_width + smt_mask_width);

        println!(
            "APIC#{} (pkg: {}, core: {}, smt: {})",
            xapic_id, pkg_id, core_id, smt_id
        );
    }
}

fn main() {
    let cpuid = CpuId::new();

    cpuid.get_processor_brand_string().map_or_else(
        || println!("CPU model identifier not available."),
        |pbs| println!("CPU Model is: {}", pbs.as_str()),
    );
    cpuid.get_extended_topology_info().map_or_else(
        || println!("No topology information available."),
        |topoiter| {
            let mut topology: Vec<ExtendedTopologyLevel> = topoiter.collect();
            topology.reverse();

            for topolevel in topology.iter() {
                let typ = match topolevel.level_type() {
                    TopologyType::SMT => "SMT-threads",
                    TopologyType::Core => "cores",
                    _ => panic!("Topology category not supported."),
                };

                println!(
                    "At level {} the CPU has: {} {}",
                    topolevel.level_number(),
                    topolevel.processors(),
                    typ,
                );
            }
        },
    );

    println!();
    enumerate_with_legacy_leaf_1_4();

    println!();
    enumerate_with_extended_topology_info();
}
<commit_msg>Fix topology example for AMD.<commit_after>//! An example that uses CPUID to determine the system topology.
//!
//! Intel Topology is a pretty complicated subject (unfortunately):
//! https://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/
extern crate core_affinity;
extern crate raw_cpuid;

use raw_cpuid::{CpuId, ExtendedTopologyLevel, TopologyType};
use std::thread;
use std::convert::TryInto;

/// Runs CPU ID on every core in the system (to gather all APIC IDs).
///
/// # Note
/// This won't work on macOS, apparently there is no guarantee after setting the affinity
/// that a thread will really execute on the pinned core.
fn gather_all_xapic_ids() -> Vec<u8> {
    let core_ids = core_affinity::get_core_ids().unwrap();

    // Create a thread for each active CPU core.
    core_ids
        .into_iter()
        .map(|id| {
            thread::spawn(move || {
                // Pin this thread to a single CPU core.
                core_affinity::set_for_current(id);
                // Do more work after this.
                let cpuid = CpuId::new();
                cpuid
                    .get_feature_info()
                    .map_or_else(|| 0, |finfo| finfo.initial_local_apic_id())
            })
            .join()
            .unwrap_or(0)
        })
        .collect::<Vec<_>>()
}

/// Runs CPU ID on every core in the system (to gather all x2APIC IDs).
///
/// # Note
/// This won't work on macOS, apparently there is no guarantee after setting the affinity
/// that a thread will really execute on the pinned core.
fn gather_all_x2apic_ids() -> Vec<u32> {
    let core_ids = core_affinity::get_core_ids().unwrap();

    // Create a thread for each active CPU core.
    core_ids
        .into_iter()
        .map(|id| {
            thread::spawn(move || {
                // Pin this thread to a single CPU core.
                core_affinity::set_for_current(id);
                // Do more work after this.
                let cpuid = CpuId::new();
                cpuid.get_extended_topology_info().map_or_else(
                    || 0,
                    |mut topiter| topiter.next().as_ref().unwrap().x2apic_id(),
                )
            })
            .join()
            .unwrap_or(0)
        })
        .collect::<Vec<_>>()
}

fn enumerate_with_x2apic_ids() {
    let cpuid = CpuId::new();
    let mut smt_x2apic_shift: u32 = 0;
    let mut core_x2apic_shift: u32 = 0;

    cpuid.get_extended_topology_info().map_or_else(
        || println!("No topology information available."),
        |topoiter| {
            let topology: Vec<ExtendedTopologyLevel> = topoiter.collect();
            for topolevel in topology.iter() {
                match topolevel.level_type() {
                    TopologyType::SMT => {
                        smt_x2apic_shift = topolevel.shift_right_for_next_apic_id();
                    }
                    TopologyType::Core => {
                        core_x2apic_shift = topolevel.shift_right_for_next_apic_id();
                    }
                    _ => panic!("Topology category not supported."),
                };
            }
        },
    );

    println!("Enumeration of all cores in the system (with x2APIC IDs):");
    let mut all_x2apic_ids: Vec<u32> = gather_all_x2apic_ids();
    all_x2apic_ids.sort_unstable();
    for x2apic_id in all_x2apic_ids {
        let smt_select_mask = !(u32::max_value() << smt_x2apic_shift);
        let core_select_mask = (!((u32::max_value()) << core_x2apic_shift)) ^ smt_select_mask;
        let pkg_select_mask = u32::max_value() << core_x2apic_shift;

        let smt_id = x2apic_id & smt_select_mask;
        let core_id = (x2apic_id & core_select_mask) >> smt_x2apic_shift;
        let pkg_id = (x2apic_id & pkg_select_mask) >> core_x2apic_shift;

        println!(
            "x2APIC#{} (pkg: {}, core: {}, smt: {})",
            x2apic_id, pkg_id, core_id, smt_id
        );
    }
}

fn cpuid_bits_needed(count: u8) -> u8 {
    let mut mask: u8 = 0x80;
    let mut cnt: u8 = 8;

    while (cnt > 0) && ((mask & count) != mask) {
        mask >>= 1;
        cnt -= 1;
    }

    cnt
}

fn get_processor_limits() -> (u8, u8) {
    let cpuid = CpuId::new();

    // This is for AMD processors:
    if let Some(info) = cpuid.get_processor_capacity_feature_info() {
        let max_logical_processor_ids = info.num_phys_threads();
        let smt_max_cores_for_package = info.apic_id_size();

        return (max_logical_processor_ids.try_into().unwrap(), smt_max_cores_for_package.try_into().unwrap());
    }
    // This is for Intel processors:
    else if let Some(cparams) = cpuid.get_cache_parameters() {
        let max_logical_processor_ids = cpuid
            .get_feature_info()
            .map_or_else(|| 1, |finfo| finfo.max_logical_processor_ids());

        let mut smt_max_cores_for_package: u8 = 1;
        for (ecx, cache) in cparams.enumerate() {
            if ecx == 0 {
                smt_max_cores_for_package = cache.max_cores_for_package() as u8;
            }
        }

        return (max_logical_processor_ids as u8, smt_max_cores_for_package as u8);
    }

    unreachable!("Example doesn't support this CPU")
}

fn enumerate_with_xapic_id() {
    let (max_logical_processor_ids, smt_max_cores_for_package) = get_processor_limits();

    let smt_mask_width: u8 = cpuid_bits_needed(
        (max_logical_processor_ids.next_power_of_two() / smt_max_cores_for_package) - 1,
    );
    let smt_select_mask: u8 = !(u8::max_value() << smt_mask_width);
    let core_mask_width: u8 = cpuid_bits_needed(smt_max_cores_for_package - 1);
    let core_only_select_mask =
        (!(u8::max_value() << (core_mask_width + smt_mask_width))) ^ smt_select_mask;
    let pkg_select_mask = u8::max_value() << (core_mask_width + smt_mask_width);

    println!("Enumeration of all cores in the system (with APIC IDs):");
    let mut all_xapic_ids: Vec<u8> = gather_all_xapic_ids();
    all_xapic_ids.sort_unstable();

    for xapic_id in all_xapic_ids {
        let smt_id = xapic_id & smt_select_mask;
        let core_id = (xapic_id & core_only_select_mask) >> smt_mask_width;
        let pkg_id = (xapic_id & pkg_select_mask) >> (core_mask_width + smt_mask_width);

        println!(
            "APIC#{} (pkg: {}, core: {}, smt: {})",
            xapic_id, pkg_id, core_id, smt_id
        );
    }
}

fn main() {
    let cpuid = CpuId::new();

    cpuid.get_processor_brand_string().map_or_else(
        || println!("CPU model identifier not available."),
        |pbs| println!("CPU Model is: {}", pbs.as_str()),
    );
    cpuid.get_extended_topology_info().map_or_else(
        || println!("No topology information available."),
        |topoiter| {
            let mut topology: Vec<ExtendedTopologyLevel> = topoiter.collect();
            topology.reverse();

            for topolevel in topology.iter() {
                let typ = match topolevel.level_type() {
                    TopologyType::SMT => "SMT-threads",
                    TopologyType::Core => "cores",
                    _ => panic!("Topology category not supported."),
                };

                println!(
                    "At level {} the CPU has: {} {}",
                    topolevel.level_number(),
                    topolevel.processors(),
                    typ,
                );
            }
        },
    );

    println!();
    enumerate_with_xapic_id();

    println!();
    enumerate_with_x2apic_ids();
}
<|endoftext|>


<commit_before>extern crate polydraw;

use polydraw::{Application, Renderer, RenderFrame};
use polydraw::draw::{RGB, bresenham};
use polydraw::geom::point::Point;
use polydraw::geom::triangle::Triangle;

struct TriangleRenderer {
   triangle: Triangle,
}

impl TriangleRenderer {
   fn new() -> Self {
      let mult = 50;
      let triangle = Triangle::new(
         Point::new(2 * mult, 9 * mult),
         Point::new(13 * mult, 12 * mult),
         Point::new(7 * mult, 2 * mult),
      );

      TriangleRenderer {
         triangle: triangle
      }
   }
}

impl Renderer for TriangleRenderer {
   fn render(&mut self, frame: &mut RenderFrame) {
      frame.clear();

      let color = RGB::new(127, 223, 255);

      bresenham(frame, self.triangle.v0.x as i32, self.triangle.v0.y as i32, self.triangle.v1.x as i32, self.triangle.v1.y as i32, &color);
      bresenham(frame, self.triangle.v1.x as i32, self.triangle.v1.y as i32, self.triangle.v2.x as i32, self.triangle.v2.y as i32, &color);
      bresenham(frame, self.triangle.v2.x as i32, self.triangle.v2.y as i32, self.triangle.v0.x as i32, self.triangle.v0.y as i32, &color);
   }
}

fn main() {
   let mut renderer = TriangleRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Triangle")
      .run();
}
<commit_msg>Naive triangle rasterization in the triangle example<commit_after>extern crate polydraw;

use std::cmp::{min, max};

use polydraw::{Application, Renderer, RenderFrame};
use polydraw::draw::RGB;
use polydraw::geom::point::Point;
use polydraw::geom::triangle::Triangle;

struct TriangleRenderer {
   tr: Triangle,
}

impl TriangleRenderer {
   fn new() -> Self {
      let mult = 50;
      let tr = Triangle::new(
         Point::new(2 * mult, 9 * mult),
         Point::new(13 * mult, 12 * mult),
         Point::new(7 * mult, 2 * mult),
      );

      println!("orientation {:?}", orientation(&tr.a, &tr.b, &tr.c));

      TriangleRenderer {
         tr: tr
      }
   }
}

impl Renderer for TriangleRenderer {
   fn render(&mut self, frame: &mut RenderFrame) {
      frame.clear();

      let color = RGB::new(127, 223, 255);

      let a = self.tr.a;
      let b = self.tr.b;
      let c = self.tr.c;

      let min_x = max(min3(a.x, b.x, c.x), 0);
      let min_y = max(min3(a.y, b.y, c.y), 0);
      let max_x = min(max3(a.x, b.x, c.x), frame.width as i64 - 1);
      let max_y = min(max3(a.y, b.y, c.y), frame.height as i64 - 1);

      for y in min_y..max_y+1 {
         for x in min_x..max_x+1 {
            let p = Point::new(x, y);
            let w0 = orientation(&b, &c, &p);
            let w1 = orientation(&c, &a, &p);
            let w2 = orientation(&a, &b, &p);

            if w0.signum() == w1.signum() && w0.signum() == w2.signum() {
               frame.put_pixel(x as i32, y as i32, &color);
            }
         }
      }
   }
}

#[inline]
pub fn min3<T: Ord>(v1: T, v2: T, v3: T) -> T {
   min(min(v1, v2), v3)
}

#[inline]
pub fn max3<T: Ord>(v1: T, v2: T, v3: T) -> T {
   max(max(v1, v2), v3)
}

#[inline]
fn orientation(a: &Point, b: &Point, c: &Point) -> i64 {
   (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)
}

fn main() {
   let mut renderer = TriangleRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Triangle")
      .run();
}
<|endoftext|>