<commit_before>extern crate libinspire;
extern crate libads;

/// Re-export slog
///
/// Users of this library can, but don't have to use slog to build their own loggers
#[macro_use]
pub extern crate slog ;
extern crate slog_stdlog;

use slog::DrainExt;

#[macro_use]
extern crate lazy_static;
extern crate regex;
use regex::Regex;

use std::fs::File;
use std::io::{Read, BufReader};
use std::io::{Write, BufWriter};

pub struct Inspirer {
    logger: slog::Logger,
    inspire: libinspire::Api,
    ads: libads::Api,
}

impl Inspirer {
    /// Initialize 'Inspirer'
    ///
    /// Either provide a custom slog::Logger or default to the standard `log`
    /// crate.
    ///
    /// # Examples
    /// ```
    /// inspirer::Inspirer::init(None);
    /// ```
    pub fn init(logger: Option<slog::Logger>) -> Self {
        let logger = logger.unwrap_or_else(|| slog::Logger::root(slog_stdlog::StdLog.fuse(), o!()));

        Inspirer {
            logger: logger,
            // inspire: libinspire::Api::init(Some(logger)),
            inspire: libinspire::Api::init(None),
            ads: libads::Api::init(None),
        }
    }

    /// Read input from file or stdin
    ///
    /// # Examples
    /// ```
    /// ```
    pub fn get_input(&self, input_source: Option<&str>) -> String {
        let mut input_data = String::new();

        let mut input_file: File;
        let mut stdin = std::io::stdin();

        let reader: &mut Read = match input_source {
            Some(file_name) => {
                info!(self.logger, "Reading from file";
                      "file_name" => file_name);
                input_file = File::open(file_name).expect("File not found");
                &mut input_file
            }
            None => {
                info!(self.logger, "Reading from stdin");
                &mut stdin
            }
        };
        let mut reader = BufReader::new(reader);
        reader.read_to_string(&mut input_data).unwrap();

        input_data
    }

    /// Write output to file or stdout
    pub fn put_output(&self, output_dest: Option<&str>, output: Vec<String>) {
        let mut stdout = std::io::stdout();
        let mut output_file: std::fs::File;

        let writer: &mut Write = match output_dest {
            Some(file_name) => {
                info!(self.logger, "Writing to file";
                      "file_name" => file_name);
                output_file = std::fs::OpenOptions::new()
                    .append(true)
                    .create(true)
                    .open(file_name)
                    .unwrap();
                &mut output_file
            }
            None => {
                info!(self.logger, "Writing to stdout");
                // stdout.lock();
                &mut stdout
            }
        };

        let mut writer = BufWriter::new(writer);

        for o in output {
            writer.write_all(&o.as_bytes()).unwrap();
        }

        writer.flush().unwrap();
    }

    /// The `aux2key` function extracts TeX keys from LaTeX .aux files. These can be for either
    /// BibTeX or BibLaTeX.
    ///
    /// # Examples
    ///
    /// ## bibtex
    ///
    /// Inspire-formatted BibTeX key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{Abramovici:1992ah}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Abramovici:1992ah"));
    /// ```
    ///
    /// ADS-formatted BibTeX Key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{1998PhRvD..58h4020O}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("1998PhRvD..58h4020O"));
    /// ```
    ///
    /// ## biber
    ///
    /// Inspire-formatted BibLaTeX key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \abx@aux@cite{Cutler:1992tc}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Cutler:1992tc"));
    /// ```
    pub fn aux2key(&self, input_data: String) -> Vec<String> {

        lazy_static! {
            // TODO: check on the exact characters allowed in keys
            static ref AUX_REGEX: Regex = Regex::new(
                r"(\\citation|\\abx@aux@cite)\{(.+)\}").unwrap();
        }

        AUX_REGEX
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            // TODO just return the iterator: makes more sense with rayon
            .collect()
    }

    /// The blg2key function extracts missing references from bibtex logs
    ///
    /// # Examples
    ///
    /// ADS-formatted BibTeX key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r##"
    /// This is BibTeX, Version 0.99d (TeX Live 2016/Arch Linux)
    /// Capacity: max_strings=35307, hash_size=35307, hash_prime=30011
    /// The top-level auxiliary file: test_bibtex.aux
    /// The style file: unsrt.bst
    /// Database file #1: test_bibtex.bib
    /// Warning--I didn't find a database entry for "2015CQGra..32g4001L"
    /// You've used 0 entries,
    /// ....
    /// "##.to_string();
    ///
    /// assert_eq!(inspirer.blg2key(input), vec!("2015CQGra..32g4001L"));
    /// ```
    pub fn blg2key(&self, input_data: String) -> Vec<String> {

        lazy_static! {
            static ref BLG_REGEX: Regex = Regex::new(
                r#"(Warning--|WARN - )I didn't find a database entry for ["'](.+)["']"#,
            ).unwrap();
        }

        BLG_REGEX
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            // TODO just return the iterator: makes more sense with rayon
            .collect()
    }

    /// Fetch BibTeX entries
    pub fn bibtex(&self, key: &str) -> Option<String> {
        let key = Sources::from(key);

        match key {
            Sources::Inspire(k) => {
                debug!(self.logger, "Got Inspire record"; "key" => k.id);
                self.inspire.fetch_bibtex_with_key(k)
            }
            Sources::Ads(k) => {
                debug!(self.logger, "Got ADS record"; "key" => k.bibcode);
                self.ads.fetch_bibtex_with_key(k)
            }
            _ => {
                // debug!(self.logger, "Unknown record source"; "key" => key);
                debug!(self.logger, "Unknown record source");
                None
            }
        }
    }
}

#[derive(Debug,PartialEq)]
pub enum Sources<'a> {
    Inspire(libinspire::RecID<'a>),
    Ads(libads::BibCode<'a>),
    Arxiv,
    None,
}

/// Guess a likely source for a BibTeX key
///
/// Returns `Sources::None` if unable to make a good guess.
///
/// # Examples
/// ```
/// extern crate inspirer;
/// extern crate libinspire;
/// let inspirer = inspirer::Inspirer::init(None);
///
/// assert_eq!(
///     inspirer::Sources::from("Randall:1999ee"),
///     inspirer::Sources::Inspire(libinspire::RecID::new("Randall:1999ee").unwrap())
/// );
/// ```
///
/// ```
/// extern crate inspirer;
/// extern crate libads;
/// let inspirer = inspirer::Inspirer::init(None);
///
/// assert_eq!(
///     inspirer::Sources::from("1999PhRvL..83.3370R"),
///     inspirer::Sources::Ads(libads::BibCode::new("1999PhRvL..83.3370R").unwrap())
/// );
/// ```
impl<'a> From<&'a str> for Sources<'a> {
    fn from(s: &'a str) -> Sources<'a> {
        if libinspire::validate_recid(s) {
            Sources::Inspire(libinspire::RecID::new(s).unwrap())
        } else if libads::validate_bib_code(s) {
            Sources::Ads(libads::BibCode::new(s).unwrap())
        } else {
            Sources::None
        }
    }
}

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

    #[test]
    fn test_aux_bibtex_0_citations() {
        let input = r"\relax ".to_string();

        let output: Vec<String> = Vec::new();
        assert_eq!(Inspirer::init(None).aux2key(input), output);
    }

    #[test]
    fn test_aux_bibtex_1_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah"]);
    }

    #[test]
    fn test_aux_bibtex_2_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}
            \citation{Thorne:1992sdb}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah", "Thorne:1992sdb"]);
    }
}
<commit_msg>refactor: Don't borrow ref and immediately deref<commit_after>extern crate libinspire;
extern crate libads;

/// Re-export slog
///
/// Users of this library can, but don't have to use slog to build their own loggers
#[macro_use]
pub extern crate slog ;
extern crate slog_stdlog;

use slog::DrainExt;

#[macro_use]
extern crate lazy_static;
extern crate regex;
use regex::Regex;

use std::fs::File;
use std::io::{Read, BufReader};
use std::io::{Write, BufWriter};

pub struct Inspirer {
    logger: slog::Logger,
    inspire: libinspire::Api,
    ads: libads::Api,
}

impl Inspirer {
    /// Initialize 'Inspirer'
    ///
    /// Either provide a custom slog::Logger or default to the standard `log`
    /// crate.
    ///
    /// # Examples
    /// ```
    /// inspirer::Inspirer::init(None);
    /// ```
    pub fn init(logger: Option<slog::Logger>) -> Self {
        let logger = logger.unwrap_or_else(|| slog::Logger::root(slog_stdlog::StdLog.fuse(), o!()));

        Inspirer {
            logger: logger,
            // inspire: libinspire::Api::init(Some(logger)),
            inspire: libinspire::Api::init(None),
            ads: libads::Api::init(None),
        }
    }

    /// Read input from file or stdin
    ///
    /// # Examples
    /// ```
    /// ```
    pub fn get_input(&self, input_source: Option<&str>) -> String {
        let mut input_data = String::new();

        let mut input_file: File;
        let mut stdin = std::io::stdin();

        let reader: &mut Read = match input_source {
            Some(file_name) => {
                info!(self.logger, "Reading from file";
                      "file_name" => file_name);
                input_file = File::open(file_name).expect("File not found");
                &mut input_file
            }
            None => {
                info!(self.logger, "Reading from stdin");
                &mut stdin
            }
        };
        let mut reader = BufReader::new(reader);
        reader.read_to_string(&mut input_data).unwrap();

        input_data
    }

    /// Write output to file or stdout
    pub fn put_output(&self, output_dest: Option<&str>, output: Vec<String>) {
        let mut stdout = std::io::stdout();
        let mut output_file: std::fs::File;

        let writer: &mut Write = match output_dest {
            Some(file_name) => {
                info!(self.logger, "Writing to file";
                      "file_name" => file_name);
                output_file = std::fs::OpenOptions::new()
                    .append(true)
                    .create(true)
                    .open(file_name)
                    .unwrap();
                &mut output_file
            }
            None => {
                info!(self.logger, "Writing to stdout");
                // stdout.lock();
                &mut stdout
            }
        };

        let mut writer = BufWriter::new(writer);

        for o in output {
            writer.write_all(o.as_bytes()).unwrap();
        }

        writer.flush().unwrap();
    }

    /// The `aux2key` function extracts TeX keys from LaTeX .aux files. These can be for either
    /// BibTeX or BibLaTeX.
    ///
    /// # Examples
    ///
    /// ## bibtex
    ///
    /// Inspire-formatted BibTeX key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{Abramovici:1992ah}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Abramovici:1992ah"));
    /// ```
    ///
    /// ADS-formatted BibTeX Key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{1998PhRvD..58h4020O}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("1998PhRvD..58h4020O"));
    /// ```
    ///
    /// ## biber
    ///
    /// Inspire-formatted BibLaTeX key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \abx@aux@cite{Cutler:1992tc}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Cutler:1992tc"));
    /// ```
    pub fn aux2key(&self, input_data: String) -> Vec<String> {

        lazy_static! {
            // TODO: check on the exact characters allowed in keys
            static ref AUX_REGEX: Regex = Regex::new(
                r"(\\citation|\\abx@aux@cite)\{(.+)\}").unwrap();
        }

        AUX_REGEX
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            // TODO just return the iterator: makes more sense with rayon
            .collect()
    }

    /// The blg2key function extracts missing references from bibtex logs
    ///
    /// # Examples
    ///
    /// ADS-formatted BibTeX key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r##"
    /// This is BibTeX, Version 0.99d (TeX Live 2016/Arch Linux)
    /// Capacity: max_strings=35307, hash_size=35307, hash_prime=30011
    /// The top-level auxiliary file: test_bibtex.aux
    /// The style file: unsrt.bst
    /// Database file #1: test_bibtex.bib
    /// Warning--I didn't find a database entry for "2015CQGra..32g4001L"
    /// You've used 0 entries,
    /// ....
    /// "##.to_string();
    ///
    /// assert_eq!(inspirer.blg2key(input), vec!("2015CQGra..32g4001L"));
    /// ```
    pub fn blg2key(&self, input_data: String) -> Vec<String> {

        lazy_static! {
            static ref BLG_REGEX: Regex = Regex::new(
                r#"(Warning--|WARN - )I didn't find a database entry for ["'](.+)["']"#,
            ).unwrap();
        }

        BLG_REGEX
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            // TODO just return the iterator: makes more sense with rayon
            .collect()
    }

    /// Fetch BibTeX entries
    pub fn bibtex(&self, key: &str) -> Option<String> {
        let key = Sources::from(key);

        match key {
            Sources::Inspire(k) => {
                debug!(self.logger, "Got Inspire record"; "key" => k.id);
                self.inspire.fetch_bibtex_with_key(k)
            }
            Sources::Ads(k) => {
                debug!(self.logger, "Got ADS record"; "key" => k.bibcode);
                self.ads.fetch_bibtex_with_key(k)
            }
            _ => {
                // debug!(self.logger, "Unknown record source"; "key" => key);
                debug!(self.logger, "Unknown record source");
                None
            }
        }
    }
}

#[derive(Debug,PartialEq)]
pub enum Sources<'a> {
    Inspire(libinspire::RecID<'a>),
    Ads(libads::BibCode<'a>),
    Arxiv,
    None,
}

/// Guess a likely source for a BibTeX key
///
/// Returns `Sources::None` if unable to make a good guess.
///
/// # Examples
/// ```
/// extern crate inspirer;
/// extern crate libinspire;
/// let inspirer = inspirer::Inspirer::init(None);
///
/// assert_eq!(
///     inspirer::Sources::from("Randall:1999ee"),
///     inspirer::Sources::Inspire(libinspire::RecID::new("Randall:1999ee").unwrap())
/// );
/// ```
///
/// ```
/// extern crate inspirer;
/// extern crate libads;
/// let inspirer = inspirer::Inspirer::init(None);
///
/// assert_eq!(
///     inspirer::Sources::from("1999PhRvL..83.3370R"),
///     inspirer::Sources::Ads(libads::BibCode::new("1999PhRvL..83.3370R").unwrap())
/// );
/// ```
impl<'a> From<&'a str> for Sources<'a> {
    fn from(s: &'a str) -> Sources<'a> {
        if libinspire::validate_recid(s) {
            Sources::Inspire(libinspire::RecID::new(s).unwrap())
        } else if libads::validate_bib_code(s) {
            Sources::Ads(libads::BibCode::new(s).unwrap())
        } else {
            Sources::None
        }
    }
}

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

    #[test]
    fn test_aux_bibtex_0_citations() {
        let input = r"\relax ".to_string();

        let output: Vec<String> = Vec::new();
        assert_eq!(Inspirer::init(None).aux2key(input), output);
    }

    #[test]
    fn test_aux_bibtex_1_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah"]);
    }

    #[test]
    fn test_aux_bibtex_2_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}
            \citation{Thorne:1992sdb}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah", "Thorne:1992sdb"]);
    }
}
<|endoftext|>


<commit_before>//! [Algorithm][1] to compute the [discrete Fourier transform][2] and its
//! inverse.
//!
//! [1]: https://en.wikipedia.org/wiki/Fast_Fourier_transform
//! [2]: https://en.wikipedia.org/wiki/Discrete_Fourier_transform

// The implementation is based on:
// http://www.librow.com/articles/article-10

extern crate complex;

pub use complex::c64;

/// Perform the forward transform.
///
/// The number of points should be a power of two.
pub fn forward(data: &mut [c64]) {
    let n = data.len();
    if n < 1 || n & (n - 1) != 0 {
        panic!("expected the number of points to be a power of two");
    }
    rearrange(data, n);
    perform(data, n, false);
}

/// Perform the inverse transform.
///
/// The number of points should be a power of two.
pub fn inverse(data: &mut [c64], scaling: bool) {
    let n = data.len();
    if n < 1 || n & (n - 1) != 0 {
        panic!("expected the number of points to be a power of two");
    }
    rearrange(data, n);
    perform(data, n, true);
    if scaling {
        scale(data, n);
    }
}

#[inline(always)]
fn rearrange(data: &mut [c64], n: usize) {
    let mut target = 0;
    for position in 0..n {
        if target > position {
            data.swap(position, target);
        }
        let mut mask = n >> 1;
        while target & mask != 0 {
            target &= !mask;
            mask >>= 1;
        }
        target |= mask;
    }
}

#[inline(always)]
fn perform(data: &mut [c64], n: usize, inverse: bool) {
    use std::f64::consts::PI;

    let pi = if inverse { PI } else { -PI };
    let mut step = 1;
    while step < n {
        let jump = step << 1;
        let delta = pi / step as f64;
        let sine = (0.5 * delta).sin();
        let multiplier = c64(-2.0 * sine * sine, delta.sin());
        let mut factor = c64(1.0, 0.0);
        for group in 0..step {
            let mut pair = group;
            while pair < n {
                let match_pair = pair + step;
                let product = factor * data[match_pair];
                data[match_pair] = data[pair] - product;
                data[pair] = data[pair] + product;
                pair += jump;
            }
            factor = multiplier * factor + factor;
        }
        step <<= 1;
    }
}

#[inline(always)]
fn scale(data: &mut [c64], n: usize) {
    let factor = 1.0 / n as f64;
    for position in 0..n {
        data[position] = data[position] * factor;
    }
}
<commit_msg>Dry a bit<commit_after>//! [Algorithm][1] to compute the [discrete Fourier transform][2] and its
//! inverse.
//!
//! [1]: https://en.wikipedia.org/wiki/Fast_Fourier_transform
//! [2]: https://en.wikipedia.org/wiki/Discrete_Fourier_transform

// The implementation is based on:
// http://www.librow.com/articles/article-10

extern crate complex;

pub use complex::c64;

macro_rules! power_of_two(
    ($n:expr) => (if $n < 1 || $n & ($n - 1) != 0 {
        panic!("expected the number of points to be a power of two");
    });
);

/// Perform the forward transform.
///
/// The number of points should be a power of two.
pub fn forward(data: &mut [c64]) {
    let n = data.len();
    power_of_two!(n);
    rearrange(data, n);
    perform(data, n, false);
}

/// Perform the inverse transform.
///
/// The number of points should be a power of two.
pub fn inverse(data: &mut [c64], scaling: bool) {
    let n = data.len();
    power_of_two!(n);
    rearrange(data, n);
    perform(data, n, true);
    if scaling {
        scale(data, n);
    }
}

#[inline(always)]
fn rearrange(data: &mut [c64], n: usize) {
    let mut target = 0;
    for position in 0..n {
        if target > position {
            data.swap(position, target);
        }
        let mut mask = n >> 1;
        while target & mask != 0 {
            target &= !mask;
            mask >>= 1;
        }
        target |= mask;
    }
}

#[inline(always)]
fn perform(data: &mut [c64], n: usize, inverse: bool) {
    use std::f64::consts::PI;

    let pi = if inverse { PI } else { -PI };
    let mut step = 1;
    while step < n {
        let jump = step << 1;
        let delta = pi / step as f64;
        let sine = (0.5 * delta).sin();
        let multiplier = c64(-2.0 * sine * sine, delta.sin());
        let mut factor = c64(1.0, 0.0);
        for group in 0..step {
            let mut pair = group;
            while pair < n {
                let match_pair = pair + step;
                let product = factor * data[match_pair];
                data[match_pair] = data[pair] - product;
                data[pair] = data[pair] + product;
                pair += jump;
            }
            factor = multiplier * factor + factor;
        }
        step <<= 1;
    }
}

#[inline(always)]
fn scale(data: &mut [c64], n: usize) {
    let factor = 1.0 / n as f64;
    for position in 0..n {
        data[position] = data[position] * factor;
    }
}
<|endoftext|>


<commit_before>
// Copyright 2017 The gltf Library Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(missing_docs)]

//! glTF 2.0 loader
//!
//! This crate is intended to load [glTF 2.0], a file format designed for the
//! efficient runtime transmission of 3D scenes. The crate aims to provide
//! rustic utilities that make working with glTF simple and intuitive.
//!
//! [glTF 2.0]: https://www.khronos.org/gltf
//!
//! ## Installation
//!
//! Add `gltf` version 0.9 to your `Cargo.toml`.
//!
//! ```toml
//! [dependencies.gltf]
//! version = "0.9"
//! ```
//!
//! ## Examples
//!
//! ### Walking the node hierarchy
//!
//! Below demonstates visiting the root [`Node`]s of every [`Scene`], printing the
//! number of children each node has.
//!
//! [`Node`]: scene/struct.Node.html
//! [`Scene`]: scene/struct.Scene.html
//! ```
//! # fn run() -> Result<(), Box<std::error::Error>> {
//! # use std::{fs, io};
//! # let path = "examples/Box.gltf";
//! use gltf::Gltf;
//! let file = fs::File::open(path)?;
//! let gltf = Gltf::from_reader(io::BufReader::new(file))?.validate_minimally()?;
//! for scene in gltf.scenes() {
//!     for node in scene.nodes() {
//!         // Do something with this node.
//!         println!(
//!             "Node {} has {} children",
//!             node.index(),
//!             node.children().count(),
//!         );
//!     }
//! }
//! # Ok(())
//! # }
//! # fn main() {
//! #    let _ = run().expect("No runtime errors");
//! # }
//! ```

extern crate cgmath;
extern crate gltf_json as json;
#[macro_use]
extern crate lazy_static;

/// Accessors for reading vertex attributes from buffer views.
pub mod accessor;

/// Animations, their channels, targets, and samplers.
pub mod animation;

/// Buffers and buffer views.
pub mod buffer;

/// Cameras and their projections.
pub mod camera;

/// Primitives for working with binary glTF.
pub mod glb;

/// **The main module - start here.**
pub mod gltf;

/// Images that may be used by textures.
pub mod image;

/// Material properties of primitives.
pub mod material;

/// Meshes and their primitives.
pub mod mesh;

/// The glTF node heirarchy.
pub mod scene;

/// Mesh skinning primitives.
pub mod skin;

/// Textures and their samplers.
pub mod texture;

pub use self::animation::Animation;
pub use self::accessor::Accessor;
pub use self::buffer::Buffer;
pub use self::camera::Camera;
pub use self::glb::Glb;
pub use self::gltf::{Gltf, Unvalidated};
pub use self::image::Image;
pub use self::material::Material;
pub use self::mesh::{Attribute, Mesh, Primitive, Semantic};
pub use self::scene::{Node, Scene};
pub use self::skin::Skin;
pub use self::texture::Texture;

/// Represents a runtime error.
#[derive(Debug)]
pub enum Error {
    /// JSON deserialization error.
    Deserialize(json::Error),

    /// GLB parsing error.
    Glb(String),

    /// `glTF` validation error.
    Validation(Vec<(json::Path, json::validation::Error)>),
}

/// Returns `true` if the slice begins with the `b"glTF"` magic string, indicating
/// a binary `glTF` asset.
///
/// # Examples
///
/// ```rust
/// assert_eq!(true, gltf::is_binary(b"glTF..."));
/// assert_eq!(false, gltf::is_binary(b"{...}"));
/// ```
pub fn is_binary(slice: &[u8]) -> bool {
    slice.starts_with(b"glTF")
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        use std::error::Error;
        write!(f, "{}", self.description())
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
         match *self {
            Error::Deserialize(_) => "deserialization error",
            Error::Glb(_) => "invalid .glb format",
            Error::Validation(_) => "invalid glTF JSON",
        }
    }
}

impl From<json::Error> for Error {
    fn from(err: json::Error) -> Self {
        Error::Deserialize(err)
    }
}

impl From<Vec<(json::Path, json::validation::Error)>> for Error {
    fn from(errs: Vec<(json::Path, json::validation::Error)>) -> Self {
        Error::Validation(errs)
    }
}
<commit_msg>Remove breaking change<commit_after>
// Copyright 2017 The gltf Library Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(missing_docs)]

//! glTF 2.0 loader
//!
//! This crate is intended to load [glTF 2.0], a file format designed for the
//! efficient runtime transmission of 3D scenes. The crate aims to provide
//! rustic utilities that make working with glTF simple and intuitive.
//!
//! [glTF 2.0]: https://www.khronos.org/gltf
//!
//! ## Installation
//!
//! Add `gltf` version 0.9 to your `Cargo.toml`.
//!
//! ```toml
//! [dependencies.gltf]
//! version = "0.9"
//! ```
//!
//! ## Examples
//!
//! ### Walking the node hierarchy
//!
//! Below demonstates visiting the root [`Node`]s of every [`Scene`], printing the
//! number of children each node has.
//!
//! [`Node`]: scene/struct.Node.html
//! [`Scene`]: scene/struct.Scene.html
//! ```
//! # fn run() -> Result<(), Box<std::error::Error>> {
//! # use std::{fs, io};
//! # let path = "examples/Box.gltf";
//! use gltf::Gltf;
//! let file = fs::File::open(path)?;
//! let gltf = Gltf::from_reader(io::BufReader::new(file))?.validate_minimally()?;
//! for scene in gltf.scenes() {
//!     for node in scene.nodes() {
//!         // Do something with this node.
//!         println!(
//!             "Node {} has {} children",
//!             node.index(),
//!             node.children().count(),
//!         );
//!     }
//! }
//! # Ok(())
//! # }
//! # fn main() {
//! #    let _ = run().expect("No runtime errors");
//! # }
//! ```

extern crate cgmath;
#[macro_use]
extern crate lazy_static;

/// Contains (de)serializable data structures that match the glTF JSON text.
#[deprecated(since = "0.9.1", note = "Will be removed in 1.0.0")]
#[doc(hidden)]
pub extern crate gltf_json as json;

/// Accessors for reading vertex attributes from buffer views.
pub mod accessor;

/// Animations, their channels, targets, and samplers.
pub mod animation;

/// Buffers and buffer views.
pub mod buffer;

/// Cameras and their projections.
pub mod camera;

/// Primitives for working with binary glTF.
pub mod glb;

/// **The main module - start here.**
pub mod gltf;

/// Images that may be used by textures.
pub mod image;

/// Material properties of primitives.
pub mod material;

/// Meshes and their primitives.
pub mod mesh;

/// The glTF node heirarchy.
pub mod scene;

/// Mesh skinning primitives.
pub mod skin;

/// Textures and their samplers.
pub mod texture;

pub use self::animation::Animation;
pub use self::accessor::Accessor;
pub use self::buffer::Buffer;
pub use self::camera::Camera;
pub use self::glb::Glb;
pub use self::gltf::{Gltf, Unvalidated};
pub use self::image::Image;
pub use self::material::Material;
pub use self::mesh::{Attribute, Mesh, Primitive, Semantic};
pub use self::scene::{Node, Scene};
pub use self::skin::Skin;
pub use self::texture::Texture;

/// Represents a runtime error.
#[derive(Debug)]
pub enum Error {
    /// JSON deserialization error.
    Deserialize(json::Error),

    /// GLB parsing error.
    Glb(String),

    /// `glTF` validation error.
    Validation(Vec<(json::Path, json::validation::Error)>),
}

/// Returns `true` if the slice begins with the `b"glTF"` magic string, indicating
/// a binary `glTF` asset.
///
/// # Examples
///
/// ```rust
/// assert_eq!(true, gltf::is_binary(b"glTF..."));
/// assert_eq!(false, gltf::is_binary(b"{...}"));
/// ```
pub fn is_binary(slice: &[u8]) -> bool {
    slice.starts_with(b"glTF")
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        use std::error::Error;
        write!(f, "{}", self.description())
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
         match *self {
            Error::Deserialize(_) => "deserialization error",
            Error::Glb(_) => "invalid .glb format",
            Error::Validation(_) => "invalid glTF JSON",
        }
    }
}

impl From<json::Error> for Error {
    fn from(err: json::Error) -> Self {
        Error::Deserialize(err)
    }
}

impl From<Vec<(json::Path, json::validation::Error)>> for Error {
    fn from(errs: Vec<(json::Path, json::validation::Error)>) -> Self {
        Error::Validation(errs)
    }
}
<|endoftext|>


<commit_before>extern crate log;
extern crate simplelog;

use goblin::pe::PE;
use goblin::Object;
use log::{debug, error, info, trace};
use rayon::prelude::*;
use std::env;
use std::fs;
use std::io::prelude::*;
use zydis;

// TODO: this really shouldn't be public. only for testing.
// TODO: what is the `cfg(doctest)` setting?
//#[cfg(test)]
pub mod rsrc;

pub struct Config {
    pub filename: String,
}

impl Config {
    pub fn from_args(args: env::Args) -> Result<Config, &'static str> {
        let args: Vec<String> = args.collect();

        if args.len() < 2 {
            return Err("not enough arguments");
        }

        let filename = args[1].clone();
        trace!("config: parsed filename: {:?}", filename);

        Ok(Config { filename })
    }
}

pub fn setup_logging(_args: &Config) {
    simplelog::TermLogger::init(simplelog::LevelFilter::Info, simplelog::Config::default())
        .expect("failed to setup logging");
}

#[derive(Debug)]
pub enum Error {
    FileAccess,
    FileFormat,
    NotImplemented,
    ValueError,
}

fn align(i: usize, b: usize) -> usize {
    let rem = i % b;
    if rem == 0 {
        i
    } else {
        i + (b - rem)
    }
}

pub fn hexdump_ascii(b: u8) -> char {
    if b.is_ascii_graphic() || b == b' ' {
        b as char
    } else {
        '.'
    }
}

pub fn hexdump(buf: &[u8], offset: usize) -> String {
    // 01234567:  00 01 02 03 04 05 06 07  ...............
    // <prefix>   <hex col>                <ascii col>

    let padding = "  ";

    let padding_size = 2;
    let hex_col_size = 3;
    let ascii_col_size = 1;
    let prefix_size = 8 + 1;
    let newline_size = 1;
    let line_size = prefix_size
        + padding_size
        + 16 * hex_col_size
        + padding_size
        + 16 * ascii_col_size
        + newline_size;
    let line_count = align(buf.len(), 0x10) / 0x10;

    let mut ret = String::with_capacity(line_count * line_size);

    let mut line = String::with_capacity(line_size);
    let mut remaining_count = buf.len();
    for line_index in 0..line_count {
        let line_elem_count = 0x10.min(remaining_count);
        let padding_elem_count = 0x10 - line_elem_count;

        // 01234567:  00 01 02 03 04 05 06 07  ...............
        // ^^^^^^^^^
        line.push_str(format!("{:08x}:", offset + 0x10 * line_index).as_str());

        // 01234567:  00 01 02 03 04 05 06 07  ...............
        //          ^^
        line.push_str(padding);

        // 01234567:  00 01 02 03 04 05 06 07  ...............
        //            ^^^
        for elem in &buf[line_index..line_index + line_elem_count] {
            line.push_str(format!("{:02x} ", elem).as_str());
        }
        for _ in 0..padding_elem_count {
            line.push_str("   ");
        }

        // 01234567:  00 01 02 03 04 05 06 07  ...............
        //                                   ^^
        line.push_str(padding);

        // 01234567:  00 01 02 03 04 05 06 07  ...............
        //                                     ^
        for elem in &buf[line_index..line_index + line_elem_count] {
            line.push(hexdump_ascii(*elem))
        }
        for _ in 0..padding_elem_count {
            line.push(' ');
        }
        line.push_str(padding);

        // 01234567:  00 01 02 03 04 05 06 07  ...............
        //                                                    ^
        line.push('\n');

        ret.push_str(line.as_str());
        line.truncate(0x0);
        remaining_count -= line_elem_count;
    }

    ret
}

fn foo(pe: &PE, buf: &[u8]) -> Result<(), Error> {
    info!("foo: {}", pe.name.unwrap_or("(unknown)"));

    info!("bitness: {}", if pe.is_64 { "64" } else { "32" });
    info!("image base: 0x{:x}", pe.image_base);
    info!("entry rva: 0x{:x}", pe.entry);

    // like:
    //
    //     sections:
    //       - .text
    //         raw size:     0x18aa00
    //         virtual size: 0x18a9a8
    info!("sections:");
    for section in pe.sections.iter() {
        if section.real_name.is_some() {
            info!(
                "  - {} ({})",
                String::from_utf8_lossy(&section.name[..]),
                section
                    .real_name
                    .as_ref()
                    .unwrap_or(&"(unknown)".to_string())
            );
        } else {
            info!("  - {}", String::from_utf8_lossy(&section.name[..]));
        }

        info!("    raw size:     0x{:x}", section.size_of_raw_data);
        info!("    virtual size: 0x{:x}", section.virtual_size);

        // TODO: figure out if we will work with usize, or u64, or what, then assert usize is ok.
        // `usize::max_value()`
        let mut secbuf = vec![0; align(section.virtual_size as usize, 0x200)];

        {
            let secsize = section.size_of_raw_data as usize;
            let rawbuf = &mut secbuf[..secsize];
            let pstart = section.pointer_to_raw_data as usize;
            rawbuf.copy_from_slice(&buf[pstart..pstart + secsize]);
        }

        info!(
            "\n{}",
            hexdump(
                &secbuf[..0x1C],
                pe.image_base + section.virtual_address as usize
            )
        );

        let decoder =
            zydis::Decoder::new(zydis::MachineMode::Long64, zydis::AddressWidth::_64).unwrap();
        let insns: Vec<_> = secbuf
            .par_windows(0x10)
            .map(|ibuf| decoder.decode(ibuf))
            .collect();

        info!("total instructions: {}", insns.len());

        info!(
            "successful disassembles: {}",
            insns.par_iter().filter(|insn| insn.is_ok()).count()
        );

        info!(
            "valid instructions: {}",
            insns
                .par_iter()
                .filter(|insn| match insn {
                    Ok(Some(_)) => true,
                    _ => false,
                })
                .count()
        );
    }

    Ok(())
}

pub fn read_file(filename: &str) -> Result<Vec<u8>, Error> {
    debug!("read_file: {:?}", filename);

    let mut buf = Vec::new();
    {
        debug!("reading file: {}", filename);
        let mut f = match fs::File::open(filename) {
            Ok(f) => f,
            Err(_) => {
                error!("failed to open file: {}", filename);
                return Err(Error::FileAccess);
            }
        };
        let bytes_read = match f.read_to_end(&mut buf) {
            Ok(c) => c,
            Err(_) => {
                error!("failed to read entire file: {}", filename);
                return Err(Error::FileAccess);
            }
        };
        debug!("read {} bytes", bytes_read);
        if bytes_read < 0x10 {
            error!("file too small: {}", filename);
            return Err(Error::FileFormat);
        }
    }

    Ok(buf)
}

pub struct Workspace {
    pub filename: String,
    pub buf: Vec<u8>,
}

impl Workspace {
    /// Parse the given file into its object.
    ///
    /// # Errors
    ///   - `Error::FileFormat`: when not able to be parsed by Goblin.
    ///
    /// # Examples
    ///
    /// ```
    /// use goblin::Object;
    /// use matches::matches;
    /// use lancelot::rsrc::*;
    /// let ws = get_workspace(Rsrc::K32);
    /// assert!(matches!(ws.get_obj().unwrap(), Object::PE(_)));
    /// ```
    ///
    /// you might be tempted to maintain a method `get_pe`,
    /// however, i don't think this is a good idea:
    /// its fragile because the file type may not be PE.
    /// therefore, force clients to be explicit:
    ///
    /// ```
    /// use goblin::Object;
    /// use lancelot::rsrc::*;
    /// let ws = get_workspace(Rsrc::K32);
    /// if let Object::PE(_) = ws.get_obj().unwrap() {
    ///     // everyone is happy!
    /// }
    /// ```
    ///
    /// TODO: demonstrate `Error::FileFormat`.
    pub fn get_obj(&self) -> Result<Object, Error> {
        let obj = match Object::parse(&self.buf) {
            Ok(o) => o,
            Err(e) => {
                error!("failed to parse file: {} error: {:?}", self.filename, e);
                return Err(Error::FileFormat);
            }
        };

        match obj {
            Object::Unknown(_) => {
                error!(
                    "unknown file format, magic: | {:02X} {:02X} | '{}{}' ",
                    self.buf[0],
                    self.buf[1],
                    hexdump_ascii(self.buf[0]),
                    hexdump_ascii(self.buf[1])
                );

                Err(Error::FileFormat)
            }
            _ => Ok(obj),
        }
    }

    pub fn get_pe(&self) -> Result<PE, Error> {
        match self.get_obj()? {
            Object::PE(pe) => {
                return Ok(pe);
            }
            _ => {
                error!("not a PE file");
                return Err(Error::ValueError);
            }
        }
    }

    /// Construct a workspace from the module with the given contents.
    ///
    /// # Errors
    ///   - `Error::FileFormat`: when not able to be parsed by Goblin.
    ///   - `Error::NotImplemented`: when not a PE file.
    ///
    /// # Examples
    ///
    /// ```
    /// use lancelot::*;
    /// use lancelot::rsrc::*;
    /// let buf = get_buf(Rsrc::K32);
    /// let ws = Workspace::from_buf("kernel32.dll", buf).unwrap();
    /// ```
    ///
    /// TODO: demonstrate ELF file behavior.
    /// TODO: demonstrate MachO file behavior.
    /// TODO: demonstrate unknown file behavior.
    pub fn from_buf(filename: &str, buf: Vec<u8>) -> Result<Workspace, Error> {
        let ws = Workspace {
            filename: filename.to_string(),
            buf: buf,
        };

        match ws.get_obj()? {
            Object::PE(_) => {
                info!("found PE file");
            }
            Object::Elf(_) => {
                return Err(Error::NotImplemented);
            }
            Object::Mach(_) => {
                return Err(Error::NotImplemented);
            }
            Object::Archive(_) => {
                return Err(Error::NotImplemented);
            }
            Object::Unknown(_) => {
                return Err(Error::NotImplemented);
            }
        }

        Ok(ws)
    }

    /// Construct a workspace from the module at given a file path.
    ///
    /// ```
    /// use lancelot::*;
    /// use lancelot::rsrc::*;
    /// let path = get_path(Rsrc::K32);
    /// // This test resource file is mangled. Needs to be fixed before parsing.
    /// // Otherwise, the following would work:
    /// // let ws = Workspace::from_file(&path).unwrap();
    /// ```
    pub fn from_file(filename: &str) -> Result<Workspace, Error> {
        let buf = read_file(filename)?;
        Workspace::from_buf(filename, buf)
    }
}

pub fn run(args: &Config) -> Result<(), Error> {
    debug!("filename: {:?}", args.filename);
    let ws = Workspace::from_file(&args.filename)?;

    if let Object::PE(pe) = ws.get_obj()? {
        foo(&pe, &ws.buf).expect("failed to foo");
    }

    Ok(())
}
<commit_msg>lib: parse sections during load<commit_after>extern crate log;
extern crate simplelog;

use goblin::pe::PE;
use goblin::Object;
use log::{debug, error, info, trace};
use rayon::prelude::*;
use std::env;
use std::fs;
use std::io::prelude::*;
use zydis;

// TODO: this really shouldn't be public. only for testing.
// TODO: what is the `cfg(doctest)` setting?
//#[cfg(test)]
pub mod rsrc;

pub struct Config {
    pub filename: String,
}

impl Config {
    pub fn from_args(args: env::Args) -> Result<Config, &'static str> {
        let args: Vec<String> = args.collect();

        if args.len() < 2 {
            return Err("not enough arguments");
        }

        let filename = args[1].clone();
        trace!("config: parsed filename: {:?}", filename);

        Ok(Config { filename })
    }
}

pub fn setup_logging(_args: &Config) {
    simplelog::TermLogger::init(simplelog::LevelFilter::Info, simplelog::Config::default())
        .expect("failed to setup logging");
}

#[derive(Debug)]
pub enum Error {
    FileAccess,
    FileFormat,
    NotImplemented,
    ValueError,
}

fn align(i: usize, b: usize) -> usize {
    let rem = i % b;
    if rem == 0 {
        i
    } else {
        i + (b - rem)
    }
}

pub fn hexdump_ascii(b: u8) -> char {
    if b.is_ascii_graphic() || b == b' ' {
        b as char
    } else {
        '.'
    }
}

pub fn hexdump(buf: &[u8], offset: usize) -> String {
    // 01234567:  00 01 02 03 04 05 06 07  ...............
    // <prefix>   <hex col>                <ascii col>

    let padding = "  ";

    let padding_size = 2;
    let hex_col_size = 3;
    let ascii_col_size = 1;
    let prefix_size = 8 + 1;
    let newline_size = 1;
    let line_size = prefix_size
        + padding_size
        + 16 * hex_col_size
        + padding_size
        + 16 * ascii_col_size
        + newline_size;
    let line_count = align(buf.len(), 0x10) / 0x10;

    let mut ret = String::with_capacity(line_count * line_size);

    let mut line = String::with_capacity(line_size);
    let mut remaining_count = buf.len();
    for line_index in 0..line_count {
        let line_elem_count = 0x10.min(remaining_count);
        let padding_elem_count = 0x10 - line_elem_count;

        // 01234567:  00 01 02 03 04 05 06 07  ...............
        // ^^^^^^^^^
        line.push_str(format!("{:08x}:", offset + 0x10 * line_index).as_str());

        // 01234567:  00 01 02 03 04 05 06 07  ...............
        //          ^^
        line.push_str(padding);

        // 01234567:  00 01 02 03 04 05 06 07  ...............
        //            ^^^
        for elem in &buf[line_index..line_index + line_elem_count] {
            line.push_str(format!("{:02x} ", elem).as_str());
        }
        for _ in 0..padding_elem_count {
            line.push_str("   ");
        }

        // 01234567:  00 01 02 03 04 05 06 07  ...............
        //                                   ^^
        line.push_str(padding);

        // 01234567:  00 01 02 03 04 05 06 07  ...............
        //                                     ^
        for elem in &buf[line_index..line_index + line_elem_count] {
            line.push(hexdump_ascii(*elem))
        }
        for _ in 0..padding_elem_count {
            line.push(' ');
        }
        line.push_str(padding);

        // 01234567:  00 01 02 03 04 05 06 07  ...............
        //                                                    ^
        line.push('\n');

        ret.push_str(line.as_str());
        line.truncate(0x0);
        remaining_count -= line_elem_count;
    }

    ret
}

fn foo(ws: &Workspace) -> Result<(), Error> {
    if let Object::PE(pe) = ws.get_obj().unwrap() {
        info!("module: {}", pe.name.unwrap_or("(unknown)"));

        info!("bitness: {}", if pe.is_64 { "64" } else { "32" });
        info!("image base: 0x{:x}", pe.image_base);
        info!("entry rva: 0x{:x}", pe.entry);

        // like:
        //
        //     sections:
        //       - .text
        //         raw size:     0x18aa00
        //         virtual size: 0x18a9a8
        info!("sections:");
        for section in ws.sections.iter() {
            info!("  - {}", section.name);
            info!("    virtual address: 0x{:x}", section.addr);
            info!("    virtual size: 0x{:x}", section.buf.len());

            info!(
                "\n{}",
                hexdump(&section.buf[..0x1C], pe.image_base + section.addr as usize)
            );

            let decoder =
                zydis::Decoder::new(zydis::MachineMode::Long64, zydis::AddressWidth::_64).unwrap();
            let insns: Vec<_> = section
                .buf
                .par_windows(0x10)
                .map(|ibuf| decoder.decode(ibuf))
                .collect();

            info!("total instructions: {}", insns.len());

            info!(
                "successful disassembles: {}",
                insns.par_iter().filter(|insn| insn.is_ok()).count()
            );

            info!(
                "valid instructions: {}",
                insns
                    .par_iter()
                    .filter(|insn| match insn {
                        Ok(Some(_)) => true,
                        _ => false,
                    })
                    .count()
            );
        }
    }

    Ok(())
}

pub fn read_file(filename: &str) -> Result<Vec<u8>, Error> {
    debug!("read_file: {:?}", filename);

    let mut buf = Vec::new();
    {
        debug!("reading file: {}", filename);
        let mut f = match fs::File::open(filename) {
            Ok(f) => f,
            Err(_) => {
                error!("failed to open file: {}", filename);
                return Err(Error::FileAccess);
            }
        };
        let bytes_read = match f.read_to_end(&mut buf) {
            Ok(c) => c,
            Err(_) => {
                error!("failed to read entire file: {}", filename);
                return Err(Error::FileAccess);
            }
        };
        debug!("read {} bytes", bytes_read);
        if bytes_read < 0x10 {
            error!("file too small: {}", filename);
            return Err(Error::FileFormat);
        }
    }

    Ok(buf)
}

pub struct Section {
    pub name: String,
    pub addr: u32,
    pub buf: Vec<u8>,
}

pub struct Workspace {
    pub filename: String,
    pub buf: Vec<u8>,
    pub sections: Vec<Section>,
}

impl Workspace {
    /// Parse the given file into its object.
    ///
    /// # Errors
    ///   - `Error::FileFormat`: when not able to be parsed by Goblin.
    ///
    /// # Examples
    ///
    /// ```
    /// use goblin::Object;
    /// use matches::matches;
    /// use lancelot::rsrc::*;
    /// let ws = get_workspace(Rsrc::K32);
    /// assert!(matches!(ws.get_obj().unwrap(), Object::PE(_)));
    /// ```
    ///
    /// you might be tempted to maintain a method `get_pe`,
    /// however, i don't think this is a good idea:
    /// its fragile because the file type may not be PE.
    /// therefore, force clients to be explicit:
    ///
    /// ```
    /// use goblin::Object;
    /// use lancelot::rsrc::*;
    /// let ws = get_workspace(Rsrc::K32);
    /// if let Object::PE(_) = ws.get_obj().unwrap() {
    ///     // everyone is happy!
    /// }
    /// ```
    ///
    /// TODO: demonstrate `Error::FileFormat`.
    pub fn get_obj(&self) -> Result<Object, Error> {
        let obj = match Object::parse(&self.buf) {
            Ok(o) => o,
            Err(e) => {
                error!("failed to parse file: {} error: {:?}", self.filename, e);
                return Err(Error::FileFormat);
            }
        };

        match obj {
            Object::Unknown(_) => {
                error!(
                    "unknown file format, magic: | {:02X} {:02X} | '{}{}' ",
                    self.buf[0],
                    self.buf[1],
                    hexdump_ascii(self.buf[0]),
                    hexdump_ascii(self.buf[1])
                );

                Err(Error::FileFormat)
            }
            _ => Ok(obj),
        }
    }

    pub fn get_pe(&self) -> Result<PE, Error> {
        match self.get_obj()? {
            Object::PE(pe) => {
                return Ok(pe);
            }
            _ => {
                error!("not a PE file");
                return Err(Error::ValueError);
            }
        }
    }

    /// Construct a workspace from the module with the given contents.
    ///
    /// # Errors
    ///   - `Error::FileFormat`: when not able to be parsed by Goblin.
    ///   - `Error::NotImplemented`: when not a PE file.
    ///
    /// # Examples
    ///
    /// ```
    /// use lancelot::*;
    /// use lancelot::rsrc::*;
    /// let buf = get_buf(Rsrc::K32);
    /// let ws = Workspace::from_buf("kernel32.dll", buf).unwrap();
    /// ```
    ///
    /// TODO: demonstrate ELF file behavior.
    /// TODO: demonstrate MachO file behavior.
    /// TODO: demonstrate unknown file behavior.
    pub fn from_buf(filename: &str, buf: Vec<u8>) -> Result<Workspace, Error> {
        let mut ws = Workspace {
            filename: filename.to_string(),
            buf: buf.clone(),
            sections: vec![],
        };

        match ws.get_obj()? {
            Object::PE(pe) => {
                info!("found PE file");

                ws.sections
                    .extend(pe.sections.iter().map(|section| -> Section {
                        // TODO: i'm sure this can be abused.
                        // TODO: add tests for weird section names.
                        let name = String::from_utf8_lossy(&section.name[..]).into_owned();

                        // TODO: figure out if we will work with usize, or u64, or what,
                        // then assert usize is ok.
                        // ref: `usize::max_value()`
                        let mut secbuf = vec![0; align(section.virtual_size as usize, 0x200)];

                        {
                            let secsize = section.size_of_raw_data as usize;
                            let rawbuf = &mut secbuf[..secsize];
                            let pstart = section.pointer_to_raw_data as usize;
                            rawbuf.copy_from_slice(&buf[pstart..pstart + secsize]);
                        }

                        Section {
                            name: name,
                            addr: section.virtual_address,
                            buf: secbuf,
                        }
                    }));
            }
            Object::Elf(_) => {
                return Err(Error::NotImplemented);
            }
            Object::Mach(_) => {
                return Err(Error::NotImplemented);
            }
            Object::Archive(_) => {
                return Err(Error::NotImplemented);
            }
            Object::Unknown(_) => {
                return Err(Error::NotImplemented);
            }
        }

        Ok(ws)
    }

    /// Construct a workspace from the module at given a file path.
    ///
    /// ```
    /// use lancelot::*;
    /// use lancelot::rsrc::*;
    /// let path = get_path(Rsrc::K32);
    /// // This test resource file is mangled. Needs to be fixed before parsing.
    /// // Otherwise, the following would work:
    /// // let ws = Workspace::from_file(&path).unwrap();
    /// ```
    pub fn from_file(filename: &str) -> Result<Workspace, Error> {
        let buf = read_file(filename)?;
        Workspace::from_buf(filename, buf)
    }
}

pub fn run(args: &Config) -> Result<(), Error> {
    debug!("filename: {:?}", args.filename);
    let ws = Workspace::from_file(&args.filename)?;

    if let Object::PE(_) = ws.get_obj()? {
        foo(&ws).expect("failed to foo");
    }

    Ok(())
}
<|endoftext|>


<commit_before>extern crate regex;

use regex::Regex;

// Idea taken from:
//   http://blog.amjith.com/fuzzyfinder-in-10-lines-of-python
pub fn explore<'a>(list: &'a [&'a str], query: &'a [char]) -> Vec<&'a str> {
    let pattern: String = query.iter()
                        .map(|ch| format!("(?i){}.*?", ch)) // (?i) for case insensitive
                        .collect();
    let re = Regex::new(&pattern).unwrap();

    let mut suggestions: Vec<(usize, usize, &str)> = list.iter()
        .map(|item| (re.find(item), *item))
        .filter(|tup| tup.0.is_some())
        .map(|(m, item)| (m.unwrap(), item))
        .map(|(m, item)| (m.as_str().len(), m.start(), item))
        .collect();

    suggestions.sort();
    suggestions.iter().map(|&(_, _, item)| item).collect()
}

/// Get the version of the program.
pub fn version() -> String {
    let (maj, min, pat) = (option_env!("CARGO_PKG_VERSION_MAJOR"),
                           option_env!("CARGO_PKG_VERSION_MINOR"),
                           option_env!("CARGO_PKG_VERSION_PATCH"));

    match (maj, min, pat) {
        (Some(maj), Some(min), Some(pat)) => format!("{}.{}.{}", maj, min, pat),
        _ => "".to_string(),
    }
}

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

    const LIST: [&'static str; 4] = [
        "/some/deeper/path/users.rs",
        "/some/path/api_user.rs",
        "/some/path/user_group.rs",
        "foobar.rs",
    ];

    #[test]
    fn it_gets_best_matches() {
        let query = ['u', 's', 'r'];
        let expected = vec![
            "/some/path/user_group.rs",
            "/some/path/api_user.rs",
            "/some/deeper/path/users.rs",
        ];

        assert_eq!(expected, explore(&LIST, &query));
    }

    #[test]
    fn it_is_case_insensitive() {
        let query = ['U', 's', 'R'];
        let expected = vec![
            "/some/path/user_group.rs",
            "/some/path/api_user.rs",
            "/some/deeper/path/users.rs",
        ];

        assert_eq!(expected, explore(&LIST, &query));
    }

    #[test]
    fn it_returns_the_same_on_empty_query() {
        let query = [];
        let expected: Vec<&str> = LIST.iter().map(|&s| s).collect();

        assert_eq!(expected, explore(&LIST, &query));
    }
}
<commit_msg>Escape special regex chars from user input.<commit_after>extern crate regex;

use regex::Regex;

/// Get the version of the program.
pub fn version() -> String {
    let (maj, min, pat) = (option_env!("CARGO_PKG_VERSION_MAJOR"),
                           option_env!("CARGO_PKG_VERSION_MINOR"),
                           option_env!("CARGO_PKG_VERSION_PATCH"));

    match (maj, min, pat) {
        (Some(maj), Some(min), Some(pat)) => format!("{}.{}.{}", maj, min, pat),
        _ => "".to_string(),
    }
}

// Idea taken from:
//   http://blog.amjith.com/fuzzyfinder-in-10-lines-of-python
pub fn explore<'a>(list: &'a [&'a str], query: &'a [char]) -> Vec<&'a str> {
    let pattern = build_pattern(query);
    let re = Regex::new(&pattern).unwrap();

    let mut suggestions: Vec<(usize, usize, &str)> = list.iter()
        .map(|item| (re.find(item), *item))
        .filter(|tup| tup.0.is_some())
        .map(|(m, item)| (m.unwrap(), item))
        .map(|(m, item)| (m.as_str().len(), m.start(), item))
        .collect();

    suggestions.sort();
    suggestions.iter().map(|&(_, _, item)| item).collect()
}

fn build_pattern<'a>(query: &'a [char]) -> String {
    query.iter()
        .map(|ch| regex::escape(&ch.to_string()))
        .map(|esc| format!("(?i){}.*?", esc)) // (?i) for case insensitive
        .collect()
}

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

    const LIST: [&'static str; 6] = [
        "/some/deeper/path/users.rs",
        "/some/path/api_user.rs",
        "/some/path/user_group.rs",
        "foobar.rs",
        "reserved?*.rs",
        "ßℝ💣",
    ];

    #[test]
    fn it_gets_best_matches() {
        let query = ['u', 's', 'r'];
        let expected = vec![
            "/some/path/user_group.rs",
            "/some/path/api_user.rs",
            "/some/deeper/path/users.rs",
        ];

        assert_eq!(expected, explore(&LIST, &query));
    }

    #[test]
    fn it_is_case_insensitive() {
        let query = ['U', 's', 'R'];
        let expected = vec![
            "/some/path/user_group.rs",
            "/some/path/api_user.rs",
            "/some/deeper/path/users.rs",
        ];

        assert_eq!(expected, explore(&LIST, &query));
    }

    #[test]
    fn it_takes_reserved_chars() {
        let query = ['?', '*', '.'];
        let expected = vec![
            "reserved?*.rs"
        ];

        assert_eq!(expected, explore(&LIST, &query));
    }

    #[test]
    fn it_takes_special_chars() {
        let query = ['ß', '💣'];
        let expected = vec![
            "ßℝ💣"
        ];

        assert_eq!(expected, explore(&LIST, &query));
    }

    #[test]
    fn it_returns_the_same_on_empty_query() {
        let query = [];
        let expected: Vec<&str> = LIST.iter().map(|&s| s).collect();

        assert_eq!(expected, explore(&LIST, &query));
    }
}
<|endoftext|>


<commit_before>extern mod extra;
use std::rand;
use std::vec;
use std::num;
use extra::sort;

trait Arbitrary : Clone {
    fn gen() -> Self;
    fn size(&self) -> uint;
}

impl Arbitrary for uint {
    fn gen() -> uint {
        let n : uint = rand::random();
         n % num::pow_with_uint(2,10)
    }
    fn size(&self) -> uint {
        self.clone()
    }
}

impl Arbitrary for int {
    fn gen() -> int {
        let n : int = rand::random();
        n % num::pow_with_uint(2,10)
    }

    fn size(&self) -> uint {
        self.clone().to_uint()
    }
}

impl<T:Arbitrary> Arbitrary for ~[T] {
    fn gen() -> ~[T] {
        let _n : uint = rand::random();
        let n = _n % 100;
        vec::build_sized(n, |p| {
            for n.times {
                p(Arbitrary::gen());
            }
        })
    }

    fn size(&self) -> uint {
        self.len()
    }
}

fn check<T:Arbitrary>(description : &str, f : extern fn(T) -> bool) {
    let num_tests = 100;
    let mut passing = 0;
    let mut failed = ~[];
    for num_tests.times {
        let t : T = Arbitrary::gen();
        if f(t.clone()) {
            passing += 1;
        } else {
            failed.push(t);
        }
    }
    if passing == num_tests {
        println("+++ OK, passed 100 tests");
    } else {
        println(fmt!("*** Failed '%s' on:", description));
        if failed.len() < 5 {
            // is this really the best way? can't be...
            let mut i = 0;
            for failed.len().times {
                println(fmt!("%?", failed[i]));
                i += 1;
            }
        } else {
            let mut failed_with_sizes : ~[(uint, T)] =
                failed.iter().transform(|x| (x.size(), x.clone()))
                .collect();
            sort::quick_sort(failed_with_sizes, |e1, e2| {
                e1.first() <= e2.first()
            });
            let mut i = 0;
            for 5.times {
                println(fmt!("%?", failed[i]));
                i += 1;
            }
            println("...and more");
        }
    }
}

fn main() {
    fn reverse<A:Clone>(v : ~[A]) -> ~[A] {
        // fancy optimization!
        if (v.len() == 2) {
            v
        } else {
            let mut newvec = ~[];
            for v.iter().advance |e| {
                newvec.unshift(e.clone());
            }
            return newvec;
        }
    }

    fn prop_reverse_reverse_uints(v : ~[uint]) -> bool {
        reverse(reverse(v.clone())) == v
    }

    fn prop_reverse_moves_first_to_last(v : ~[uint]) -> bool {
        if v.len() > 0 {
            reverse(v.clone())[v.len() - 1] == v[0]
        } else {
            true // trivially
        }
    }

    check("reversing a list twice yields the same list",
          prop_reverse_reverse_uints);
    check("reversing a list moves first element to last",
          prop_reverse_moves_first_to_last);
}<commit_msg>re-organize to use proper tests, make reverse even buggier<commit_after>extern mod extra;
use std::rand;
use std::vec;
use std::num;
use extra::sort;

trait Arbitrary : Clone {
    fn gen() -> Self;
    fn size(&self) -> uint;
}

impl Arbitrary for uint {
    fn gen() -> uint {
        let n : uint = rand::random();
         n % num::pow_with_uint(2,10)
    }
    fn size(&self) -> uint {
        self.clone()
    }
}

impl Arbitrary for int {
    fn gen() -> int {
        let n : int = rand::random();
        n % num::pow_with_uint(2,10)
    }

    fn size(&self) -> uint {
        self.clone().to_uint()
    }
}

impl<T:Arbitrary> Arbitrary for ~[T] {
    fn gen() -> ~[T] {
        let _n : uint = rand::random();
        let n = _n % 100;
        vec::build_sized(n, |p| {
            for n.times {
                p(Arbitrary::gen());
            }
        })
    }

    fn size(&self) -> uint {
        self.len()
    }
}

/**
 * quick_check
 *   description: a string describing what the property being tested is
 *   f: function that takes arbitrary input and returns whether
 *      the invariant held.
 *
 *   returns whether all the tests passed.
 */
fn quick_check<T:Arbitrary>(description : &str,
                            f : extern fn(T) -> bool) -> bool {
    let num_tests = 100;
    let mut passing = 0;
    let mut failed = ~[];
    for num_tests.times {
        let t : T = Arbitrary::gen();
        if f(t.clone()) {
            passing += 1;
        } else {
            failed.push(t);
        }
    }
    if passing == num_tests {
        println(fmt!("+++ OK, passed 100 tests for %s", description));
        return true;
    } else {
        println(fmt!("*** Failed '%s' on:", description));
        if failed.len() < 5 {
            // is this really the best way? can't be...
            let mut i = 0;
            for failed.len().times {
                println(fmt!("%?", failed[i]));
                i += 1;
            }
        } else {
            let mut failed_with_sizes : ~[(uint, T)] =
                failed.iter().transform(|x| (x.size(), x.clone()))
                .collect();
            sort::quick_sort(failed_with_sizes, |e1, e2| {
                e1.first() <= e2.first()
            });
            let mut i = 0;
            for 5.times {
                println(fmt!("%?", failed_with_sizes[i].second()));
                i += 1;
            }
            println("...and more");
        }
        return false;
    }
}

#[test]
fn reverse_uint_vecs() {
    fn reverse<A:Clone>(v : ~[A]) -> ~[A] {
        let mut newvec = ~[];
        for v.iter().advance |e| {
            // NOTE(dbp 2013-07-25): This is intentionally buggy.
            newvec.push(e.clone());
        }
        return newvec;
    }

    fn prop_reverse_reverse_uints(v : ~[uint]) -> bool {
        reverse(reverse(v.clone())) == v
    }

    fn prop_reverse_moves_first_to_last(v : ~[uint]) -> bool {
        if v.len() > 0 {
            reverse(v.clone())[v.len() - 1] == v[0]
        } else {
            true // trivially
        }
    }

    assert!(
        quick_check("reversing a list twice yields the same list",
                    prop_reverse_reverse_uints));
    assert!(
        !quick_check("reversing a list moves first to last",
                     prop_reverse_moves_first_to_last));
}
<|endoftext|>


<commit_before>//! A `cargo` subcommand for the client-side Web.

#![deny(
    missing_debug_implementations,
    trivial_numeric_casts,
    unstable_features,
    unused_import_braces,
    unused_qualifications
)]

#[macro_use]
extern crate structopt;
extern crate clap;
extern crate digest;
extern crate futures;
extern crate http;
extern crate hyper;
extern crate libflate;
extern crate notify;
extern crate pbr;
extern crate reqwest;
extern crate serde;
extern crate sha1;
extern crate sha2;
extern crate tar;
extern crate tempfile;
extern crate toml;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
extern crate base_x;
extern crate handlebars;
extern crate indexmap;
extern crate regex;
extern crate unicode_categories;
extern crate walkdir;
extern crate websocket;
#[macro_use]
extern crate lazy_static;
extern crate directories;
extern crate percent_encoding;

extern crate parity_wasm;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate rustc_demangle;

extern crate ansi_term;
extern crate cargo_metadata;

extern crate memmap;
extern crate semver;

extern crate atty;
extern crate open;
#[macro_use]
extern crate failure;

mod cargo_shim;

#[macro_use]
mod utils;
mod build;
mod chrome_devtools;
mod cmd_build;
mod cmd_deploy;
mod cmd_prepare_emscripten;
mod cmd_start;
mod cmd_test;
mod config;
mod deployment;
mod emscripten;
mod error;
mod http_utils;
mod package;
mod project_dirs;
mod test_chromium;
mod wasm;
mod wasm_context;
mod wasm_export_main;
mod wasm_export_table;
mod wasm_gc;
mod wasm_hook_grow;
mod wasm_inline_js;
mod wasm_intrinsics;
mod wasm_js_export;
mod wasm_js_snippet;
mod wasm_runtime;

use std::ffi::OsStr;
use std::net::{IpAddr, ToSocketAddrs};
use std::path::PathBuf;

use build::{Backend, BuildArgs};
use cargo_shim::MessageFormat;
use error::Error;
use wasm_runtime::RuntimeKind;

/// CLI for `cargo-web`
#[derive(Debug, StructOpt)]
#[structopt(name = "cargo-web")]
#[structopt(about = "A `cargo` subcommand for the client-side web.")]
#[structopt(raw(global_setting = "structopt::clap::AppSettings::ColoredHelp"))]
#[structopt(raw(setting = "structopt::clap::AppSettings::VersionlessSubcommands"))]
#[structopt(rename_all = "kebab-case")]
pub enum CargoWebOpts {
    /// Compile a local package and all of its dependencies
    Build(BuildOpts),
    /// Typecheck a local package and all of its dependencies
    Check(CheckOpts),
    /// Deploys your project so that it's ready to be served statically
    Deploy(DeployOpts),
    /// Fetches and installs prebuilt Emscripten packages
    PrepareEmscripten(PrepareEmscriptenOpts),
    /// Runs an embedded web server, which serves the built project
    Start(StartOpts),
    /// Compiles and runs tests
    Test(TestOpts),
    #[doc(hidden)]
    #[structopt(raw(setting = "structopt::clap::AppSettings::Hidden"))]
    __Nonexhaustive,
}

/// Run a subcommand based on a configuration
pub fn run(cfg: CargoWebOpts) -> Result<(), Error> {
    match cfg {
        CargoWebOpts::Build(BuildOpts {
            build_args,
            build_target,
            ext,
        }) => cmd_build::command_build(BuildArgs::new(build_args, ext, build_target)?),
        CargoWebOpts::Check(CheckOpts {
            build_args,
            build_target,
            ext,
        }) => cmd_build::command_check(BuildArgs::new(build_args, ext, build_target)?),
        CargoWebOpts::Deploy(DeployOpts { build_args, output }) => {
            cmd_deploy::command_deploy(build_args.into(), output)
        }
        CargoWebOpts::PrepareEmscripten(_) => cmd_prepare_emscripten::command_prepare_emscripten(),
        CargoWebOpts::Start(StartOpts {
            build_args,
            build_target,
            auto_reload,
            open,
            port,
            host,
        }) => cmd_start::command_start(
            BuildArgs::from(build_args).with_target(build_target),
            host,
            port,
            open,
            auto_reload,
        ),
        CargoWebOpts::Test(TestOpts {
            build_args,
            nodejs,
            no_run,
            passthrough,
        }) => {
            let pass_os = passthrough.iter().map(OsStr::new).collect::<Vec<_>>();
            cmd_test::command_test(build_args.into(), nodejs, no_run, &pass_os)
        }
        CargoWebOpts::__Nonexhaustive => unreachable!(),
    }
}

/// Options for `cargo web build`
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct BuildOpts {
    #[structopt(flatten)]
    build_args: Build,
    #[structopt(flatten)]
    ext: BuildExt,
    #[structopt(flatten)]
    build_target: Target,
}

/// Options for `cargo web check`
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct CheckOpts {
    #[structopt(flatten)]
    build_args: Build,
    #[structopt(flatten)]
    ext: BuildExt,
    #[structopt(flatten)]
    build_target: Target,
}

/// Options for `cargo web deploy`
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct DeployOpts {
    /// Output directory; the default is `$CARGO_TARGET_DIR/deploy`
    #[structopt(short = "o", long, parse(from_os_str))]
    output: Option<PathBuf>,
    #[structopt(flatten)]
    build_args: Build,
}

/// Options for `cargo web prepare-emscripten`
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct PrepareEmscriptenOpts {
    #[doc(hidden)]
    #[structopt(raw(set = "structopt::clap::ArgSettings::Hidden"))]
    __reserved: bool,
}

/// Options for `cargo web start`
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct StartOpts {
    /// Bind the server to this address
    #[structopt(
        long,
        parse(try_from_str = "resolve_host"),
        default_value = "localhost"
    )]
    host: IpAddr,
    /// Bind the server to this port
    #[structopt(long, default_value = "8000")]
    port: u16,
    /// Open browser after server starts
    #[structopt(long)]
    open: bool,
    /// Will try to automatically reload the page on rebuild
    #[structopt(long)]
    auto_reload: bool,
    #[structopt(flatten)]
    build_target: Target,
    #[structopt(flatten)]
    build_args: Build,
}

/// Options for `cargo web test`
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct TestOpts {
    /// Compile, but don't run tests
    #[structopt(long)]
    no_run: bool,
    /// Uses Node.js to run the tests
    #[structopt(long)]
    nodejs: bool,
    #[structopt(flatten)]
    build_args: Build,
    /// all additional arguments will be passed through to the test runner
    passthrough: Vec<String>,
}

/// Select a target to build
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
struct Target {
    /// Build only this package's library
    #[structopt(long, group = "target_type")]
    lib: bool,
    /// Build only the specified binary
    #[structopt(long, group = "target_type")]
    bin: Option<String>,
    /// Build only the specified example
    #[structopt(long, group = "target_type")]
    example: Option<String>,
    /// Build only the specified test target
    #[structopt(long, group = "target_type")]
    test: Option<String>,
    /// Build only the specified benchmark target
    #[structopt(long, group = "target_type")]
    bench: Option<String>,
}

impl Default for Target {
    fn default() -> Self {
        Self {
            lib: false,
            bin: None,
            example: None,
            test: None,
            bench: None,
        }
    }
}

/// Specify additional build options
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
struct BuildExt {
    /// Selects the stdout output format
    #[structopt(
        long,
        default_value = "human",
        parse(try_from_str),
        raw(possible_values = "&[\"human\", \"json\"]"),
        raw(set = "structopt::clap::ArgSettings::NextLineHelp")
    )]
    message_format: MessageFormat,
    /// Selects the type of JavaScript runtime which will be generated
    /// (Only valid when targeting `wasm32-unknown-unknown`). [possible values:
    /// standalone, library-es6, web-extension]
    #[structopt(
        long,
        parse(try_from_str),
        raw(set = "structopt::clap::ArgSettings::NextLineHelp")
    )]
    runtime: Option<RuntimeKind>,
}

impl Default for BuildExt {
    fn default() -> Self {
        Self {
            message_format: MessageFormat::Json,
            runtime: None,
        }
    }
}

/// Build configuration for one or more targets
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
struct Build {
    /// Package to build
    #[structopt(short = "p", long)]
    pub package: Option<String>,
    /// Additional features to build (space-delimited list)
    #[structopt(long, group = "build_features")]
    pub features: Option<String>,
    /// Build all available features
    #[structopt(long, group = "build_features")]
    pub all_features: bool,
    /// Do not build the `default` feature
    #[structopt(long, group = "build_features")]
    pub no_default_features: bool,
    /// Won't try to download Emscripten; will always use the system one
    #[structopt(long)]
    pub use_system_emscripten: bool,
    /// Build artifacts in release mode, with optimizations
    #[structopt(long)]
    pub release: bool,
    /// Target triple to build for, overriding setting in `Web.toml`. If not
    /// specified in `Web.toml`, default target is `wasm32-unknown-unknown`.
    #[structopt(
        long,
        parse(try_from_str),
        raw(
            possible_values = "&[\"wasm32-unknown-unknown\", \"wasm32-unknown-emscripten\", \"asmjs-unknown-emscripten\"]"
        ),
        raw(set = "structopt::clap::ArgSettings::NextLineHelp")
    )]
    pub target: Option<Backend>,
    /// Use verbose output
    #[structopt(short = "v", long)]
    pub verbose: bool,
}

impl Default for Build {
    /// Returns a sensible default config.
    ///
    /// # Note
    /// If you want to change the target triple, use `Into`, e.g.
    /// `target: "asmjs-unknown-emscripten".into()`
    fn default() -> Self {
        Self {
            package: None,
            features: None,
            all_features: false,
            no_default_features: false,
            use_system_emscripten: false,
            release: false,
            target: None,
            verbose: false,
        }
    }
}

/// Resolve hostname to IP address
fn resolve_host(host: &str) -> std::io::Result<IpAddr> {
    (host, 0)
        .to_socket_addrs()
        .map(|itr| itr.map(|a| a.ip()).collect::<Vec<_>>()[0])
}
<commit_msg>fix --no-default-features flag<commit_after>//! A `cargo` subcommand for the client-side Web.

#![deny(
    missing_debug_implementations,
    trivial_numeric_casts,
    unstable_features,
    unused_import_braces,
    unused_qualifications
)]

#[macro_use]
extern crate structopt;
extern crate clap;
extern crate digest;
extern crate futures;
extern crate http;
extern crate hyper;
extern crate libflate;
extern crate notify;
extern crate pbr;
extern crate reqwest;
extern crate serde;
extern crate sha1;
extern crate sha2;
extern crate tar;
extern crate tempfile;
extern crate toml;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
extern crate base_x;
extern crate handlebars;
extern crate indexmap;
extern crate regex;
extern crate unicode_categories;
extern crate walkdir;
extern crate websocket;
#[macro_use]
extern crate lazy_static;
extern crate directories;
extern crate percent_encoding;

extern crate parity_wasm;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate rustc_demangle;

extern crate ansi_term;
extern crate cargo_metadata;

extern crate memmap;
extern crate semver;

extern crate atty;
extern crate open;
#[macro_use]
extern crate failure;

mod cargo_shim;

#[macro_use]
mod utils;
mod build;
mod chrome_devtools;
mod cmd_build;
mod cmd_deploy;
mod cmd_prepare_emscripten;
mod cmd_start;
mod cmd_test;
mod config;
mod deployment;
mod emscripten;
mod error;
mod http_utils;
mod package;
mod project_dirs;
mod test_chromium;
mod wasm;
mod wasm_context;
mod wasm_export_main;
mod wasm_export_table;
mod wasm_gc;
mod wasm_hook_grow;
mod wasm_inline_js;
mod wasm_intrinsics;
mod wasm_js_export;
mod wasm_js_snippet;
mod wasm_runtime;

use std::ffi::OsStr;
use std::net::{IpAddr, ToSocketAddrs};
use std::path::PathBuf;

use build::{Backend, BuildArgs};
use cargo_shim::MessageFormat;
use error::Error;
use wasm_runtime::RuntimeKind;

/// CLI for `cargo-web`
#[derive(Debug, StructOpt)]
#[structopt(name = "cargo-web")]
#[structopt(about = "A `cargo` subcommand for the client-side web.")]
#[structopt(raw(global_setting = "structopt::clap::AppSettings::ColoredHelp"))]
#[structopt(raw(setting = "structopt::clap::AppSettings::VersionlessSubcommands"))]
#[structopt(rename_all = "kebab-case")]
pub enum CargoWebOpts {
    /// Compile a local package and all of its dependencies
    Build(BuildOpts),
    /// Typecheck a local package and all of its dependencies
    Check(CheckOpts),
    /// Deploys your project so that it's ready to be served statically
    Deploy(DeployOpts),
    /// Fetches and installs prebuilt Emscripten packages
    PrepareEmscripten(PrepareEmscriptenOpts),
    /// Runs an embedded web server, which serves the built project
    Start(StartOpts),
    /// Compiles and runs tests
    Test(TestOpts),
    #[doc(hidden)]
    #[structopt(raw(setting = "structopt::clap::AppSettings::Hidden"))]
    __Nonexhaustive,
}

/// Run a subcommand based on a configuration
pub fn run(cfg: CargoWebOpts) -> Result<(), Error> {
    match cfg {
        CargoWebOpts::Build(BuildOpts {
            build_args,
            build_target,
            ext,
        }) => cmd_build::command_build(BuildArgs::new(build_args, ext, build_target)?),
        CargoWebOpts::Check(CheckOpts {
            build_args,
            build_target,
            ext,
        }) => cmd_build::command_check(BuildArgs::new(build_args, ext, build_target)?),
        CargoWebOpts::Deploy(DeployOpts { build_args, output }) => {
            cmd_deploy::command_deploy(build_args.into(), output)
        }
        CargoWebOpts::PrepareEmscripten(_) => cmd_prepare_emscripten::command_prepare_emscripten(),
        CargoWebOpts::Start(StartOpts {
            build_args,
            build_target,
            auto_reload,
            open,
            port,
            host,
        }) => cmd_start::command_start(
            BuildArgs::from(build_args).with_target(build_target),
            host,
            port,
            open,
            auto_reload,
        ),
        CargoWebOpts::Test(TestOpts {
            build_args,
            nodejs,
            no_run,
            passthrough,
        }) => {
            let pass_os = passthrough.iter().map(OsStr::new).collect::<Vec<_>>();
            cmd_test::command_test(build_args.into(), nodejs, no_run, &pass_os)
        }
        CargoWebOpts::__Nonexhaustive => unreachable!(),
    }
}

/// Options for `cargo web build`
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct BuildOpts {
    #[structopt(flatten)]
    build_args: Build,
    #[structopt(flatten)]
    ext: BuildExt,
    #[structopt(flatten)]
    build_target: Target,
}

/// Options for `cargo web check`
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct CheckOpts {
    #[structopt(flatten)]
    build_args: Build,
    #[structopt(flatten)]
    ext: BuildExt,
    #[structopt(flatten)]
    build_target: Target,
}

/// Options for `cargo web deploy`
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct DeployOpts {
    /// Output directory; the default is `$CARGO_TARGET_DIR/deploy`
    #[structopt(short = "o", long, parse(from_os_str))]
    output: Option<PathBuf>,
    #[structopt(flatten)]
    build_args: Build,
}

/// Options for `cargo web prepare-emscripten`
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct PrepareEmscriptenOpts {
    #[doc(hidden)]
    #[structopt(raw(set = "structopt::clap::ArgSettings::Hidden"))]
    __reserved: bool,
}

/// Options for `cargo web start`
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct StartOpts {
    /// Bind the server to this address
    #[structopt(
        long,
        parse(try_from_str = "resolve_host"),
        default_value = "localhost"
    )]
    host: IpAddr,
    /// Bind the server to this port
    #[structopt(long, default_value = "8000")]
    port: u16,
    /// Open browser after server starts
    #[structopt(long)]
    open: bool,
    /// Will try to automatically reload the page on rebuild
    #[structopt(long)]
    auto_reload: bool,
    #[structopt(flatten)]
    build_target: Target,
    #[structopt(flatten)]
    build_args: Build,
}

/// Options for `cargo web test`
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct TestOpts {
    /// Compile, but don't run tests
    #[structopt(long)]
    no_run: bool,
    /// Uses Node.js to run the tests
    #[structopt(long)]
    nodejs: bool,
    #[structopt(flatten)]
    build_args: Build,
    /// all additional arguments will be passed through to the test runner
    passthrough: Vec<String>,
}

/// Select a target to build
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
struct Target {
    /// Build only this package's library
    #[structopt(long, group = "target_type")]
    lib: bool,
    /// Build only the specified binary
    #[structopt(long, group = "target_type")]
    bin: Option<String>,
    /// Build only the specified example
    #[structopt(long, group = "target_type")]
    example: Option<String>,
    /// Build only the specified test target
    #[structopt(long, group = "target_type")]
    test: Option<String>,
    /// Build only the specified benchmark target
    #[structopt(long, group = "target_type")]
    bench: Option<String>,
}

impl Default for Target {
    fn default() -> Self {
        Self {
            lib: false,
            bin: None,
            example: None,
            test: None,
            bench: None,
        }
    }
}

/// Specify additional build options
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
struct BuildExt {
    /// Selects the stdout output format
    #[structopt(
        long,
        default_value = "human",
        parse(try_from_str),
        raw(possible_values = "&[\"human\", \"json\"]"),
        raw(set = "structopt::clap::ArgSettings::NextLineHelp")
    )]
    message_format: MessageFormat,
    /// Selects the type of JavaScript runtime which will be generated
    /// (Only valid when targeting `wasm32-unknown-unknown`). [possible values:
    /// standalone, library-es6, web-extension]
    #[structopt(
        long,
        parse(try_from_str),
        raw(set = "structopt::clap::ArgSettings::NextLineHelp")
    )]
    runtime: Option<RuntimeKind>,
}

impl Default for BuildExt {
    fn default() -> Self {
        Self {
            message_format: MessageFormat::Json,
            runtime: None,
        }
    }
}

/// Build configuration for one or more targets
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
struct Build {
    /// Package to build
    #[structopt(short = "p", long)]
    pub package: Option<String>,
    /// Additional features to build (space-delimited list)
    #[structopt(long, group = "build_features")]
    pub features: Option<String>,
    /// Build all available features
    #[structopt(long, group = "build_features")]
    pub all_features: bool,
    /// Do not build the `default` feature
    #[structopt(long)]
    pub no_default_features: bool,
    /// Won't try to download Emscripten; will always use the system one
    #[structopt(long)]
    pub use_system_emscripten: bool,
    /// Build artifacts in release mode, with optimizations
    #[structopt(long)]
    pub release: bool,
    /// Target triple to build for, overriding setting in `Web.toml`. If not
    /// specified in `Web.toml`, default target is `wasm32-unknown-unknown`.
    #[structopt(
        long,
        parse(try_from_str),
        raw(
            possible_values = "&[\"wasm32-unknown-unknown\", \"wasm32-unknown-emscripten\", \"asmjs-unknown-emscripten\"]"
        ),
        raw(set = "structopt::clap::ArgSettings::NextLineHelp")
    )]
    pub target: Option<Backend>,
    /// Use verbose output
    #[structopt(short = "v", long)]
    pub verbose: bool,
}

impl Default for Build {
    /// Returns a sensible default config.
    ///
    /// # Note
    /// If you want to change the target triple, use `Into`, e.g.
    /// `target: "asmjs-unknown-emscripten".into()`
    fn default() -> Self {
        Self {
            package: None,
            features: None,
            all_features: false,
            no_default_features: false,
            use_system_emscripten: false,
            release: false,
            target: None,
            verbose: false,
        }
    }
}

/// Resolve hostname to IP address
fn resolve_host(host: &str) -> std::io::Result<IpAddr> {
    (host, 0)
        .to_socket_addrs()
        .map(|itr| itr.map(|a| a.ip()).collect::<Vec<_>>()[0])
}
<|endoftext|>


<commit_before>extern crate num;
extern crate rand;
extern crate rutorch;

use rutorch::*;
use std::ops::{Index, IndexMut};
use rand::Rng;
//use std::convert::From;
use num::Num;
use std::cmp::max;

struct BaseIter<'a, T, P: 'a + Index<isize>> {
	idx: usize,
	parent: &'a P,
	t: std::marker::PhantomData<T>,
}

impl <'a, T, P: Index<isize> >BaseIter<'a, T, P> {
	fn new(parent: &'a P) -> Self {
		BaseIter { idx: 0, parent: parent, t: std::default::Default::default()}
	}
}

trait Storage {
	fn new() -> Self;
	fn sized(len: isize) -> Self;
}

struct FloatStorage {
	t: *mut THFloatStorage,
}

impl Storage for FloatStorage {
	fn new() -> Self {
		unsafe { FloatStorage  {t : THFloatStorage_new()} }
	}
	fn sized(size: isize) ->Self {
		unsafe { FloatStorage  {t : THFloatStorage_newWithSize(size)} }
	}
}

impl FloatStorage {
	fn iter(&mut self) -> BaseIter<f32, FloatStorage> {
		BaseIter::new(self)
	}
}

impl Index<isize> for FloatStorage {
	type Output = f32;

	fn index(&self, idx: isize) -> &f32 {
		unsafe {&*(*self.t).data.offset(idx)}
	}
}

impl IndexMut<isize> for FloatStorage {
	fn index_mut(&mut self, idx: isize) -> &mut f32 {
		unsafe {&mut *(*self.t).data.offset(idx)}
	}
}

impl <'a, O: Copy, T>Iterator for BaseIter<'a, O, T>
	where T: std::ops::Index<isize, Output=O> {
	type Item = O;

	fn next(&mut self) -> Option<O> {
		// XXX check length ---
		let ret = *(*self.parent).index(self.idx as isize);
		self.idx += 1;
		Some(ret)
	}
}

//fn from(args: &ArgsArray<T>) -> Self;

trait Tensor<'a> : Index<&'a [isize]> {
	fn new() -> Self;
	fn sized(size: &'a [isize]) -> Self;
	fn randn(dims: &'a [isize]) -> Self;
}

struct FloatTensor {
	t: *mut THFloatTensor,
	storage: FloatStorage,
	dims: Vec<isize>,
}

impl <'a>Tensor<'a> for FloatTensor {
	fn new() -> Self {
		unsafe { FloatTensor { t : THFloatTensor_new(), storage: FloatStorage::new(), dims: Vec::new()  }}
	}
	fn sized(dims: &'a [isize]) -> Self {
		let size = dims.iter().product();
		let storage = FloatStorage::sized(size);
		let strides = vec![1; dims.len()];
		let mut t = THFloatTensor { size : dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
			stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
			nDimension : dims.len() as i32, storage: storage.t, storageOffset: 0, refcount: 1,
			flag: TH_TENSOR_REFCOUNTED as i8};
		FloatTensor {t : &mut t, storage: storage, dims: Vec::from(dims)}
	}
	fn randn(dims: &'a [isize]) -> Self {
		/* XXX */
		let t = Tensor::sized(dims);
//		x = random::<f32>();
		t
	}
}

impl <'a> Index<&'a [isize]> for FloatTensor {
	type Output = f32;

	fn index(&self, idx: &'a [isize]) -> &f32 {
		let mut index : isize = 0;
		let lastidx = max(0, idx.len() as isize - 1) as usize;
		if idx.len() != self.dims.len() { panic!("bad dimlen")}
		for i in 0..lastidx {
			if idx[i] >= self.dims[i] { panic!("bad dimlen")}
			index += idx[i] * self.dims[i]
		}
		if idx[lastidx] >= self.dims[lastidx] { panic!("bad dimlen")}
		index += idx[lastidx];
		&self.storage[index]
	}
}

impl <'a> IndexMut<&'a [isize]> for FloatTensor {
	fn index_mut(&mut self, idx: &'a [isize]) -> &mut f32 {
		let mut index : isize = 0;
		let lastidx = max(0, idx.len() as isize - 1) as usize;
		if idx.len() != self.dims.len() { panic!("bad dimlen")}
		for i in 0..lastidx {
			if idx[i] >= self.dims[i] { panic!("bad dimlen")}
			index += idx[i] * self.dims[i]
		}
		if idx[lastidx] >= self.dims[lastidx] { panic!("bad dimlen")}
		index += idx[lastidx];
		&mut self.storage[index]
	}
}

#[cfg(test)]
mod tests {
	use super::*;
    #[test]
    fn it_works() {

    }
}
<commit_msg>implement iter_mut<commit_after>extern crate num;
extern crate rand;
extern crate rutorch;

use rutorch::*;
use std::ops::{Index, IndexMut};
use rand::Rng;
//use std::convert::From;
use num::Num;
use std::cmp::max;

struct BaseIter<'a, T, P: 'a + Index<isize>> {
	idx: usize,
	parent: &'a P,
	t: std::marker::PhantomData<T>,
}

struct BaseIterMut<'a, T, P: 'a + Index<isize>> {
	idx: usize,
	parent: &'a mut P,
	t: std::marker::PhantomData<T>,
}

impl <'a, T, P: Index<isize, Output=T> >BaseIter<'a, T, P> {
	fn new(parent: &'a P) -> Self {
		BaseIter { idx: 0, parent: parent, t: std::default::Default::default()}
	}
}

impl <'a, T, P: Index<isize, Output=T> >BaseIterMut<'a, T, P> {
	fn new(parent: &'a mut P) -> Self {
		BaseIterMut { idx: 0, parent: parent, t: std::default::Default::default()}
	}
}

trait Storage {
	fn new() -> Self;
	fn sized(len: isize) -> Self;
}

struct FloatStorage {
	t: *mut THFloatStorage,
}

impl Storage for FloatStorage {
	fn new() -> Self {
		unsafe { FloatStorage  {t : THFloatStorage_new()} }
	}
	fn sized(size: isize) ->Self {
		unsafe { FloatStorage  {t : THFloatStorage_newWithSize(size)} }
	}
}

impl FloatStorage {
	fn iter(&self) -> BaseIter<f32, FloatStorage> {
		BaseIter::new(self)
	}
	fn iter_mut(&mut self) -> BaseIterMut<f32, FloatStorage> {
		BaseIterMut::new(self)
	}
}

impl Index<isize> for FloatStorage {
	type Output = f32;

	fn index(&self, idx: isize) -> &f32 {
		unsafe {&*(*self.t).data.offset(idx)}
	}
}

impl IndexMut<isize> for FloatStorage {
	fn index_mut(&mut self, idx: isize) -> &mut f32 {
		unsafe {&mut *(*self.t).data.offset(idx)}
	}
}

impl <'a, O: 'a, T>Iterator for BaseIter<'a, O, T>
	where T: std::ops::Index<isize, Output=O> {
	type Item = &'a O;

	fn next(&mut self) -> Option<Self::Item> {
		// XXX check length ---
		let ret = (*self.parent).index(self.idx as isize);
		self.idx += 1;
		Some(&ret)
	}
}

impl <'a, O: 'a, T: 'a>Iterator for BaseIterMut<'a, O, T>
	where T: std::ops::IndexMut<isize, Output=O> {
	type Item = &'a mut O;

	fn next(&mut self) -> Option<Self::Item> {
		// XXX check length ---
		let ret = (*self.parent).index_mut(self.idx as isize);
		self.idx += 1;
		Some(ret)
	}
}

//fn from(args: &ArgsArray<T>) -> Self;

trait Tensor<'a> : Index<&'a [isize]> {
	fn new() -> Self;
	fn sized(size: &'a [isize]) -> Self;
	fn randn(dims: &'a [isize]) -> Self;
}

struct FloatTensor {
	t: *mut THFloatTensor,
	storage: FloatStorage,
	dims: Vec<isize>,
}

impl <'a>Tensor<'a> for FloatTensor {
	fn new() -> Self {
		unsafe { FloatTensor { t : THFloatTensor_new(), storage: FloatStorage::new(), dims: Vec::new()  }}
	}
	fn sized(dims: &'a [isize]) -> Self {
		let size = dims.iter().product();
		let storage = FloatStorage::sized(size);
		let strides = vec![1; dims.len()];
		let mut t = THFloatTensor { size : dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
			stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
			nDimension : dims.len() as i32, storage: storage.t, storageOffset: 0, refcount: 1,
			flag: TH_TENSOR_REFCOUNTED as i8};
		FloatTensor {t : &mut t, storage: storage, dims: Vec::from(dims)}
	}
	fn randn(dims: &'a [isize]) -> Self {
		/* XXX */
		let t = Tensor::sized(dims);
//		x = random::<f32>();
		t
	}
}

impl <'a> Index<&'a [isize]> for FloatTensor {
	type Output = f32;

	fn index(&self, idx: &'a [isize]) -> &f32 {
		let mut index : isize = 0;
		let lastidx = max(0, idx.len() as isize - 1) as usize;
		if idx.len() != self.dims.len() { panic!("bad dimlen")}
		for i in 0..lastidx {
			if idx[i] >= self.dims[i] { panic!("bad dimlen")}
			index += idx[i] * self.dims[i]
		}
		if idx[lastidx] >= self.dims[lastidx] { panic!("bad dimlen")}
		index += idx[lastidx];
		&self.storage[index]
	}
}

impl <'a> IndexMut<&'a [isize]> for FloatTensor {
	fn index_mut(&mut self, idx: &'a [isize]) -> &mut f32 {
		let mut index : isize = 0;
		let lastidx = max(0, idx.len() as isize - 1) as usize;
		if idx.len() != self.dims.len() { panic!("bad dimlen")}
		for i in 0..lastidx {
			if idx[i] >= self.dims[i] { panic!("bad dimlen")}
			index += idx[i] * self.dims[i]
		}
		if idx[lastidx] >= self.dims[lastidx] { panic!("bad dimlen")}
		index += idx[lastidx];
		&mut self.storage[index]
	}
}

#[cfg(test)]
mod tests {
	use super::*;
    #[test]
    fn it_works() {

    }
}
<|endoftext|>