<commit_before>// This file is part of Genesis.

// Genesis is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Genesis is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with Genesis.  If not, see <http://www.gnu.org/licenses/>.
use super::serial;

#[no_mangle]
#[allow(unused_must_use)]
pub extern fn arch_init() -> ! {
    unsafe {
        serial::init();
        writeln!(serial::get(), "Hello World");
    }
    loop {}
}
<commit_msg>Remove warning disable<commit_after>// This file is part of Genesis.

// Genesis is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Genesis is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with Genesis.  If not, see <http://www.gnu.org/licenses/>.
use super::serial;

#[no_mangle]
pub extern fn arch_init() -> ! {
    unsafe {
        serial::init();
        let _ = writeln!(serial::get(), "Hello World");
    }
    loop {}
}
<|endoftext|>


<commit_before>use anyhow::*;
use image::imageops::FilterType;
use image::{DynamicImage, GenericImage, GenericImageView, ImageBuffer};
use std::cmp;
use std::path::*;

use crate::app::thumbnail::{read, Options};

pub fn generate_thumbnail(image_path: &Path, thumbnailoptions: &Options) -> Result<DynamicImage> {
	let source_image = read(image_path)?;
	let (source_width, source_height) = source_image.dimensions();
	let largest_dimension = cmp::max(source_width, source_height);
	let out_dimension = cmp::min(thumbnailoptions.max_dimension, largest_dimension);

	let source_aspect_ratio: f32 = source_width as f32 / source_height as f32;
	let is_almost_square = source_aspect_ratio > 0.8 && source_aspect_ratio < 1.2;

	let mut final_image;
	if is_almost_square && thumbnailoptions.resize_if_almost_square {
		final_image = source_image.resize_exact(out_dimension, out_dimension, FilterType::Lanczos3);
	} else if thumbnailoptions.pad_to_square {
		let scaled_image = source_image.resize(out_dimension, out_dimension, FilterType::Lanczos3);
		let (scaled_width, scaled_height) = scaled_image.dimensions();
		let background = image::Rgb([255, 255 as u8, 255 as u8]);
		final_image = DynamicImage::ImageRgb8(ImageBuffer::from_pixel(
			out_dimension,
			out_dimension,
			background,
		));
		final_image.copy_from(
			&scaled_image,
			(out_dimension - scaled_width) / 2,
			(out_dimension - scaled_height) / 2,
		)?;
	} else {
		final_image = source_image.resize(out_dimension, out_dimension, FilterType::Lanczos3);
	}

	Ok(final_image)
}
<commit_msg>Thumbnail fixes (#121)<commit_after>use anyhow::*;
use image::{DynamicImage, GenericImage, GenericImageView, ImageBuffer};
use std::cmp;
use std::path::*;

use crate::app::thumbnail::{read, Options};

pub fn generate_thumbnail(image_path: &Path, options: &Options) -> Result<DynamicImage> {
	let source_image = DynamicImage::ImageRgb8(read(image_path)?.into_rgb8());
	let (source_width, source_height) = source_image.dimensions();
	let largest_dimension = cmp::max(source_width, source_height);
	let out_dimension = cmp::min(options.max_dimension, largest_dimension);

	let source_aspect_ratio: f32 = source_width as f32 / source_height as f32;
	let is_almost_square = source_aspect_ratio > 0.8 && source_aspect_ratio < 1.2;

	let mut final_image;
	if is_almost_square && options.resize_if_almost_square {
		final_image = source_image.thumbnail_exact(out_dimension, out_dimension);
	} else if options.pad_to_square {
		let scaled_image = source_image.thumbnail(out_dimension, out_dimension);
		let (scaled_width, scaled_height) = scaled_image.dimensions();
		let background = image::Rgb([255, 255 as u8, 255 as u8]);
		final_image = DynamicImage::ImageRgb8(ImageBuffer::from_pixel(
			out_dimension,
			out_dimension,
			background,
		));
		final_image.copy_from(
			&scaled_image,
			(out_dimension - scaled_width) / 2,
			(out_dimension - scaled_height) / 2,
		)?;
	} else {
		final_image = source_image.thumbnail(out_dimension, out_dimension);
	}

	Ok(final_image)
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

#[macro_use]
extern crate clap;
extern crate colored;
extern crate json;
extern crate rerast;

use json::{JsonError, JsonValue};
use std::io::{self, Write};
use rerast::{ArgBuilder, Config, RerastCompilerDriver};
use rerast::chunked_diff;
use std::str::Utf8Error;
use std::fs::{self, File};
use std::io::prelude::*;
use clap::ArgMatches;

#[derive(Clone, Debug)]
struct Error {
    message: String,
}

impl Error {
    fn new<T: Into<String>>(message: T) -> Error {
        Error {
            message: message.into(),
        }
    }
}

impl From<io::Error> for Error {
    fn from(error: io::Error) -> Error {
        Error::new(error.to_string())
    }
}

impl From<JsonError> for Error {
    fn from(error: JsonError) -> Error {
        Error::new(error.to_string())
    }
}

impl From<Utf8Error> for Error {
    fn from(error: Utf8Error) -> Error {
        Error::new(error.to_string())
    }
}

// Environment variables that we use to pass data from the outer invocation of cargo-rerast through
// to the inner invocation which runs within cargo check.
mod var_names {
    // Environment variable name, which if set, indicates that we should write our arguments out as
    // JSON before running the actual rust compiler. Hopefully eventually cargo will have a way for
    // us to query the compile commandlines without doing this sort of thing.
    pub const PRINT_ARGS_JSON: &'static str = "RERAST_PRINT_ARGS_JSON";
}

const JSON_ARGS_MARKER: &'static str = "RUSTC_ARGS_AS_JSON: ";

// Queries cargo to find the name of the current crate, then runs cargo clean to
// clean up artifacts for that package (but not dependencies). This is necessary
// in order to ensure that all the files in the current crate actually get built
// when we run cargo check. Hopefully eventually there'll be a nicer way to
// integrate with cargo such that we won't need to do this.
fn clean_local_targets() -> Result<(), Error> {
    let output = std::process::Command::new("cargo")
        .args(vec!["metadata", "--no-deps", "--format-version=1"])
        .stdout(std::process::Stdio::piped())
        .output()?;
    let metadata_str = std::str::from_utf8(output.stdout.as_slice())?;
    let parsed = json::parse(metadata_str)?;
    for package in parsed["packages"].members() {
        if let Some(name) = package["name"].as_str() {
            std::process::Command::new("cargo")
                .args(vec!["clean", "--package", name])
                .status()?;
        }
    }
    Ok(())
}

fn get_rustc_commandlines_for_local_package() -> Result<Vec<Vec<String>>, Error> {
    clean_local_targets()?;
    let current_exe = std::env::current_exe().expect("env::current_exe() failed");
    let cargo_check_output = std::process::Command::new("cargo")
        .env(var_names::PRINT_ARGS_JSON, "yes")
        .env("RUSTC_WRAPPER", current_exe)
        .args(vec!["check", "-v"])
        .stdout(std::process::Stdio::piped())
        .output()
        .expect("Failed to invoke cargo");
    let output_str = std::str::from_utf8(cargo_check_output.stdout.as_slice())
        .map_err(|e| Error::new(e.to_string()))?;
    if cargo_check_output.status.code() != Some(0) {
        return Err(Error::new(format!(
            "cargo check failed (exit code = {}). Output follows:\n{}",
            cargo_check_output
                .status
                .code()
                .map(|c| c.to_string())
                .unwrap_or_else(|| "signal".to_owned()),
            output_str
        )));
    }
    let mut result: Vec<Vec<String>> = Vec::new();
    for line in output_str.lines() {
        if line.starts_with(JSON_ARGS_MARKER) {
            let parsed = json::parse(&line[JSON_ARGS_MARKER.len()..]).map_err(|e| {
                io::Error::new(io::ErrorKind::InvalidData, e.to_string())
            })?;
            if let JsonValue::Array(values) = parsed {
                let args: Result<Vec<String>, Error> = values
                    .into_iter()
                    .map(|v| {
                        if let Some(s) = v.as_str() {
                            Ok(s.to_owned())
                        } else {
                            Err(Error::new(format!("Expected JSON string, got: {:?}", v)))
                        }
                    })
                    .collect();
                result.push(args?);
            }
        }
    }
    Ok(result)
}

enum Action {
    Diff,
    DiffCmd(String),
    ForceWrite { backup: bool },
}

impl Action {
    fn from_matches(matches: &ArgMatches) -> Result<Action, Error> {
        let mut actions = Vec::new();
        if matches.is_present("diff") {
            actions.push(Action::Diff)
        }
        if let Some(diff_cmd) = matches.value_of("diff_cmd") {
            actions.push(Action::DiffCmd(diff_cmd.to_owned()));
        }
        if matches.is_present("force") {
            actions.push(Action::ForceWrite {
                backup: matches.is_present("backup"),
            })
        }
        if actions.len() > 1 {
            actions.clear();
        }
        actions.into_iter().next().ok_or_else(|| {
            Error::new("Exactly one of --diff, --diff_cmd or --force is currently required")
        })
    }

    fn process(&self, filename: &str, new_contents: &str) -> Result<(), Error> {
        match *self {
            Action::Diff => {
                let mut current_contents = String::new();
                File::open(filename)?.read_to_string(&mut current_contents)?;
                chunked_diff::print_diff(filename, &current_contents, new_contents);
            }
            Action::DiffCmd(ref diff_cmd) => {
                // rustfmt has a native diff built-in. If that were extracted into a separate crate,
                // we could reuse that instead of calling out to an external diff.
                let mut diff_cmd_iter = diff_cmd.split(" ");
                let command = diff_cmd_iter.next().unwrap_or("diff");
                let mut diff_process = std::process::Command::new(command)
                    .args(
                        ArgBuilder::from_args(diff_cmd_iter)
                            .arg(filename)
                            .arg("-")
                            .build(),
                    )
                    .stdin(std::process::Stdio::piped())
                    .spawn()
                    .map_err(|e| {
                        io::Error::new(e.kind(), format!("Error running '{}': {}", diff_cmd, e))
                    })?;
                diff_process
                    .stdin
                    .as_mut()
                    .unwrap()
                    .write_all(new_contents.as_bytes())?;
                diff_process.wait()?;
            }
            Action::ForceWrite { backup } => {
                // Write to a temporary file so that we don't truncate the file if writing fails.
                let tmp_file = "rerast-tmp";
                fs::File::create(tmp_file)?.write_all(new_contents.as_bytes())?;
                if backup {
                    fs::rename(filename, filename.to_owned() + ".bk")?;
                }
                fs::rename(tmp_file, filename)?;
            }
        }
        Ok(())
    }
}

fn get_replacement_kind_and_arg(matches: &ArgMatches) -> Result<(&'static str, String), Error> {
    let mut result = Vec::new();
    if let Some(s) = matches.value_of("search") {
        result.push(("replace", s.to_owned()));
    }
    if let Some(s) = matches.value_of("search_type") {
        result.push(("replace_type", s.to_owned()));
    }
    if let Some(s) = matches.value_of("search_pattern") {
        result.push(("replace_pattern", s.to_owned()));
    }
    if let Some(s) = matches.value_of("search_trait_ref") {
        result.push(("replace_trait_ref", s.to_owned()));
    }
    if result.len() > 1 {
        result.clear();
    }
    result.into_iter().next().ok_or_else(|| {
        Error::new("--replace_with requires exactly one kind of --search* argument is required.")
    })
}

fn cargo_rerast() -> Result<(), Error> {
    let mut args: Vec<String> = std::env::args().collect();
    // We want the help message to say "cargo rerast" not "cargo-rerast rerast".
    args[0] = "cargo".to_owned();
    let matches = clap::App::new("Rerast")
        .subcommand(
            clap::SubCommand::with_name("rerast")
                .about("Replace Rust code based on typed, syntactic patterns")
                .args_from_usage(
                    "--rules_file=[FILE] 'Path to a rule file'
                     --use=[USE_STATEMENT]... 'Use statements required by rule'
                     -p, --placeholders=[PLACEHOLDERS] 'e.g. <T>(o: option<T>)'
                     -s, --search=[CODE] 'Expression to search for'
                     --search_type=[CODE] 'Type to search for'
                     --search_pattern=[CODE] 'Pattern to search for'
                     --search_trait_ref=[TRAIT] 'Trait to search for'
                     -r, --replace_with=[CODE] 'Replacement code'
                     --file=[FILE]... 'Only apply to these root files and their submodules'
                     --diff_cmd=[COMMAND] 'Diff changes with the specified diff command'
                     --color=[always/never] 'Force color on or off'
                     --debug_snippet=[CODE_SNIPPET] 'A snippet of code that you think should \
                                                     match or list_all to list all checked \
                                                     snippets.'
                                      \
                     --diff 'Diff changes'
                     --force 'Overwrite files',
                     --backup 'Rename old files with a .bk extension',
                     --verbose 'Print additional information about what's happening'",
                ),
        )
        .get_matches_from(&args);
    let matches = matches.subcommand_matches("rerast").ok_or_else(|| {
        Error::new("This binary is intended to be run as `cargo rerast` not run directly.")
    })?;
    let config = Config {
        verbose: matches.is_present("verbose"),
        debug_snippet: matches.value_of("debug_snippet").unwrap_or("").to_owned(),
        files: values_t!(matches.values_of("file"), String).ok(),
    };
    match matches.value_of("color") {
        Some("always") => colored::control::set_override(true),
        Some("never") => colored::control::set_override(false),
        Some(_) => return Err(Error::new("Invalid value for --color")),
        _ => {}
    }
    let rules = if let Some(replacement) = matches.value_of("replace_with") {
        let (replace_kind, search) = get_replacement_kind_and_arg(matches)?;
        let mut placeholders = matches.value_of("placeholders").unwrap_or("").to_owned();
        if !placeholders.contains('(') {
            placeholders = "(".to_owned() + &placeholders + ")";
        }
        let mut rules = String::new();
        if let Some(deps) = matches.values_of("use") {
            for dependency in deps {
                rules.push_str("use ");
                rules.push_str(dependency);
                rules.push_str(";\n");
            }
        }
        rules.push_str("pub fn rule");
        rules.push_str(&placeholders);
        rules.push_str("{");
        rules.push_str(replace_kind);
        rules.push_str("!(");
        rules.push_str(&search);
        rules.push_str(" => ");
        rules.push_str(replacement);
        rules.push_str(");}");
        rules
    } else if matches.is_present("search") || matches.is_present("search_type")
        || matches.is_present("search_pattern")
        || matches.is_present("search_trait_ref")
    {
        return Err(Error::new(
            "Searching without --replace_with is not yet implemented",
        ));
    } else {
        "".to_owned()
    };
    let rules_file = matches.value_of("rules_file").unwrap_or("");
    if rules_file.is_empty() == rules.is_empty() {
        return Err(Error::new(
            "Must specify either --rules_file or both of --search and --replacement",
        ));
    }
    let action = Action::from_matches(matches)?;
    if config.verbose {
        println!("Running cargo check in order to build dependencies and get rustc commands");
    }
    let rustc_command_lines = get_rustc_commandlines_for_local_package()?;

    for rustc_args in &rustc_command_lines {
        let driver =
            RerastCompilerDriver::new(ArgBuilder::from_args(rustc_args.iter().skip(1).cloned()));
        let code_filename = driver.code_filename().ok_or_else(|| {
            Error::new(format!(
                "Failed to determine code filename from: {:?}",
                &rustc_args[2..]
            ))
        })?;
        if config.verbose {
            println!("Processing {}", code_filename);
        }
        match driver.apply_rules_from_string_or_file(rules.clone(), &rules_file, config.clone()) {
            Ok(output) => {
                if config.verbose && output.updated_files.is_empty() {
                    println!("No matches found in {} or submodules", code_filename);
                }
                for (filename, new_contents) in output.updated_files {
                    action.process(&filename, &new_contents)?;
                }
            }
            Err(errors) => {
                return Err(Error::new(errors.to_string()));
            }
        }
    }
    Ok(())
}

fn pass_through_to_actual_compiler() {
    let args: Vec<_> = std::env::args().skip(2).collect();
    std::process::Command::new("rustc")
        .args(args)
        .status()
        .expect("Failed to run rustc");
}

pub fn main() {
    let driver = RerastCompilerDriver::new(ArgBuilder::from_args(std::env::args().skip(1)));
    if let Ok(_) = std::env::var(var_names::PRINT_ARGS_JSON) {
        // If cargo is calling us to get compiler configuration or is compiling
        // a dependent crate, thenp just run the compiler normally.
        if driver.args().has_arg("--print=cfg") || driver.is_compiling_dependency() {
            pass_through_to_actual_compiler();
        } else {
            let json_args: Vec<JsonValue> =
                std::env::args().map(|a| JsonValue::String(a)).collect();
            println!("{}{}", JSON_ARGS_MARKER, JsonValue::Array(json_args).dump());
            pass_through_to_actual_compiler();
        }
    } else {
        if let Err(error) = cargo_rerast() {
            eprintln!("{}", error.message);
        }
    }
}
<commit_msg>Look for matches in tests, benches and examples as well<commit_after>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

#[macro_use]
extern crate clap;
extern crate colored;
extern crate json;
extern crate rerast;

use json::{JsonError, JsonValue};
use std::io::{self, Write};
use rerast::{ArgBuilder, Config, RerastCompilerDriver};
use rerast::chunked_diff;
use std::str::Utf8Error;
use std::fs::{self, File};
use std::io::prelude::*;
use clap::ArgMatches;

#[derive(Clone, Debug)]
struct Error {
    message: String,
}

impl Error {
    fn new<T: Into<String>>(message: T) -> Error {
        Error {
            message: message.into(),
        }
    }
}

impl From<io::Error> for Error {
    fn from(error: io::Error) -> Error {
        Error::new(error.to_string())
    }
}

impl From<JsonError> for Error {
    fn from(error: JsonError) -> Error {
        Error::new(error.to_string())
    }
}

impl From<Utf8Error> for Error {
    fn from(error: Utf8Error) -> Error {
        Error::new(error.to_string())
    }
}

// Environment variables that we use to pass data from the outer invocation of cargo-rerast through
// to the inner invocation which runs within cargo check.
mod var_names {
    // Environment variable name, which if set, indicates that we should write our arguments out as
    // JSON before running the actual rust compiler. Hopefully eventually cargo will have a way for
    // us to query the compile commandlines without doing this sort of thing.
    pub const PRINT_ARGS_JSON: &'static str = "RERAST_PRINT_ARGS_JSON";
}

const JSON_ARGS_MARKER: &'static str = "RUSTC_ARGS_AS_JSON: ";

// Queries cargo to find the name of the current crate, then runs cargo clean to
// clean up artifacts for that package (but not dependencies). This is necessary
// in order to ensure that all the files in the current crate actually get built
// when we run cargo check. Hopefully eventually there'll be a nicer way to
// integrate with cargo such that we won't need to do this.
fn clean_local_targets() -> Result<(), Error> {
    let output = std::process::Command::new("cargo")
        .args(vec!["metadata", "--no-deps", "--format-version=1"])
        .stdout(std::process::Stdio::piped())
        .output()?;
    let metadata_str = std::str::from_utf8(output.stdout.as_slice())?;
    let parsed = json::parse(metadata_str)?;
    for package in parsed["packages"].members() {
        if let Some(name) = package["name"].as_str() {
            std::process::Command::new("cargo")
                .args(vec!["clean", "--package", name])
                .status()?;
        }
    }
    Ok(())
}

fn get_rustc_commandlines_for_local_package() -> Result<Vec<Vec<String>>, Error> {
    clean_local_targets()?;
    let current_exe = std::env::current_exe().expect("env::current_exe() failed");
    let cargo_check_output = std::process::Command::new("cargo")
        .env(var_names::PRINT_ARGS_JSON, "yes")
        .env("RUSTC_WRAPPER", current_exe)
        .args(vec!["check", "-v", "--tests", "--benches", "--examples"])
        .stdout(std::process::Stdio::piped())
        .output()
        .expect("Failed to invoke cargo");
    let output_str = std::str::from_utf8(cargo_check_output.stdout.as_slice())
        .map_err(|e| Error::new(e.to_string()))?;
    if cargo_check_output.status.code() != Some(0) {
        return Err(Error::new(format!(
            "cargo check failed (exit code = {}). Output follows:\n{}",
            cargo_check_output
                .status
                .code()
                .map(|c| c.to_string())
                .unwrap_or_else(|| "signal".to_owned()),
            output_str
        )));
    }
    let mut result: Vec<Vec<String>> = Vec::new();
    for line in output_str.lines() {
        if line.starts_with(JSON_ARGS_MARKER) {
            let parsed = json::parse(&line[JSON_ARGS_MARKER.len()..]).map_err(|e| {
                io::Error::new(io::ErrorKind::InvalidData, e.to_string())
            })?;
            if let JsonValue::Array(values) = parsed {
                let args: Result<Vec<String>, Error> = values
                    .into_iter()
                    .map(|v| {
                        if let Some(s) = v.as_str() {
                            Ok(s.to_owned())
                        } else {
                            Err(Error::new(format!("Expected JSON string, got: {:?}", v)))
                        }
                    })
                    .collect();
                result.push(args?);
            }
        }
    }
    Ok(result)
}

enum Action {
    Diff,
    DiffCmd(String),
    ForceWrite { backup: bool },
}

impl Action {
    fn from_matches(matches: &ArgMatches) -> Result<Action, Error> {
        let mut actions = Vec::new();
        if matches.is_present("diff") {
            actions.push(Action::Diff)
        }
        if let Some(diff_cmd) = matches.value_of("diff_cmd") {
            actions.push(Action::DiffCmd(diff_cmd.to_owned()));
        }
        if matches.is_present("force") {
            actions.push(Action::ForceWrite {
                backup: matches.is_present("backup"),
            })
        }
        if actions.len() > 1 {
            actions.clear();
        }
        actions.into_iter().next().ok_or_else(|| {
            Error::new("Exactly one of --diff, --diff_cmd or --force is currently required")
        })
    }

    fn process(&self, filename: &str, new_contents: &str) -> Result<(), Error> {
        match *self {
            Action::Diff => {
                let mut current_contents = String::new();
                File::open(filename)?.read_to_string(&mut current_contents)?;
                chunked_diff::print_diff(filename, &current_contents, new_contents);
            }
            Action::DiffCmd(ref diff_cmd) => {
                // rustfmt has a native diff built-in. If that were extracted into a separate crate,
                // we could reuse that instead of calling out to an external diff.
                let mut diff_cmd_iter = diff_cmd.split(" ");
                let command = diff_cmd_iter.next().unwrap_or("diff");
                let mut diff_process = std::process::Command::new(command)
                    .args(
                        ArgBuilder::from_args(diff_cmd_iter)
                            .arg(filename)
                            .arg("-")
                            .build(),
                    )
                    .stdin(std::process::Stdio::piped())
                    .spawn()
                    .map_err(|e| {
                        io::Error::new(e.kind(), format!("Error running '{}': {}", diff_cmd, e))
                    })?;
                diff_process
                    .stdin
                    .as_mut()
                    .unwrap()
                    .write_all(new_contents.as_bytes())?;
                diff_process.wait()?;
            }
            Action::ForceWrite { backup } => {
                // Write to a temporary file so that we don't truncate the file if writing fails.
                let tmp_file = "rerast-tmp";
                fs::File::create(tmp_file)?.write_all(new_contents.as_bytes())?;
                if backup {
                    fs::rename(filename, filename.to_owned() + ".bk")?;
                }
                fs::rename(tmp_file, filename)?;
            }
        }
        Ok(())
    }
}

fn get_replacement_kind_and_arg(matches: &ArgMatches) -> Result<(&'static str, String), Error> {
    let mut result = Vec::new();
    if let Some(s) = matches.value_of("search") {
        result.push(("replace", s.to_owned()));
    }
    if let Some(s) = matches.value_of("search_type") {
        result.push(("replace_type", s.to_owned()));
    }
    if let Some(s) = matches.value_of("search_pattern") {
        result.push(("replace_pattern", s.to_owned()));
    }
    if let Some(s) = matches.value_of("search_trait_ref") {
        result.push(("replace_trait_ref", s.to_owned()));
    }
    if result.len() > 1 {
        result.clear();
    }
    result.into_iter().next().ok_or_else(|| {
        Error::new("--replace_with requires exactly one kind of --search* argument is required.")
    })
}

fn cargo_rerast() -> Result<(), Error> {
    let mut args: Vec<String> = std::env::args().collect();
    // We want the help message to say "cargo rerast" not "cargo-rerast rerast".
    args[0] = "cargo".to_owned();
    let matches = clap::App::new("Rerast")
        .subcommand(
            clap::SubCommand::with_name("rerast")
                .about("Replace Rust code based on typed, syntactic patterns")
                .args_from_usage(
                    "--rules_file=[FILE] 'Path to a rule file'
                     --use=[USE_STATEMENT]... 'Use statements required by rule'
                     -p, --placeholders=[PLACEHOLDERS] 'e.g. <T>(o: option<T>)'
                     -s, --search=[CODE] 'Expression to search for'
                     --search_type=[CODE] 'Type to search for'
                     --search_pattern=[CODE] 'Pattern to search for'
                     --search_trait_ref=[TRAIT] 'Trait to search for'
                     -r, --replace_with=[CODE] 'Replacement code'
                     --file=[FILE]... 'Only apply to these root files and their submodules'
                     --diff_cmd=[COMMAND] 'Diff changes with the specified diff command'
                     --color=[always/never] 'Force color on or off'
                     --debug_snippet=[CODE_SNIPPET] 'A snippet of code that you think should \
                                                     match or list_all to list all checked \
                                                     snippets.'
                                      \
                     --diff 'Diff changes'
                     --force 'Overwrite files',
                     --backup 'Rename old files with a .bk extension',
                     --verbose 'Print additional information about what's happening'",
                ),
        )
        .get_matches_from(&args);
    let matches = matches.subcommand_matches("rerast").ok_or_else(|| {
        Error::new("This binary is intended to be run as `cargo rerast` not run directly.")
    })?;
    let config = Config {
        verbose: matches.is_present("verbose"),
        debug_snippet: matches.value_of("debug_snippet").unwrap_or("").to_owned(),
        files: values_t!(matches.values_of("file"), String).ok(),
    };
    match matches.value_of("color") {
        Some("always") => colored::control::set_override(true),
        Some("never") => colored::control::set_override(false),
        Some(_) => return Err(Error::new("Invalid value for --color")),
        _ => {}
    }
    let rules = if let Some(replacement) = matches.value_of("replace_with") {
        let (replace_kind, search) = get_replacement_kind_and_arg(matches)?;
        let mut placeholders = matches.value_of("placeholders").unwrap_or("").to_owned();
        if !placeholders.contains('(') {
            placeholders = "(".to_owned() + &placeholders + ")";
        }
        let mut rules = String::new();
        if let Some(deps) = matches.values_of("use") {
            for dependency in deps {
                rules.push_str("use ");
                rules.push_str(dependency);
                rules.push_str(";\n");
            }
        }
        rules.push_str("pub fn rule");
        rules.push_str(&placeholders);
        rules.push_str("{");
        rules.push_str(replace_kind);
        rules.push_str("!(");
        rules.push_str(&search);
        rules.push_str(" => ");
        rules.push_str(replacement);
        rules.push_str(");}");
        rules
    } else if matches.is_present("search") || matches.is_present("search_type")
        || matches.is_present("search_pattern")
        || matches.is_present("search_trait_ref")
    {
        return Err(Error::new(
            "Searching without --replace_with is not yet implemented",
        ));
    } else {
        "".to_owned()
    };
    let rules_file = matches.value_of("rules_file").unwrap_or("");
    if rules_file.is_empty() == rules.is_empty() {
        return Err(Error::new(
            "Must specify either --rules_file or both of --search and --replacement",
        ));
    }
    let action = Action::from_matches(matches)?;
    if config.verbose {
        println!("Running cargo check in order to build dependencies and get rustc commands");
    }
    let rustc_command_lines = get_rustc_commandlines_for_local_package()?;

    for rustc_args in &rustc_command_lines {
        let driver =
            RerastCompilerDriver::new(ArgBuilder::from_args(rustc_args.iter().skip(1).cloned()));
        let code_filename = driver.code_filename().ok_or_else(|| {
            Error::new(format!(
                "Failed to determine code filename from: {:?}",
                &rustc_args[2..]
            ))
        })?;
        if config.verbose {
            println!("Processing {}", code_filename);
        }
        match driver.apply_rules_from_string_or_file(rules.clone(), &rules_file, config.clone()) {
            Ok(output) => {
                if config.verbose && output.updated_files.is_empty() {
                    println!("No matches found in {} or submodules", code_filename);
                }
                for (filename, new_contents) in output.updated_files {
                    action.process(&filename, &new_contents)?;
                }
            }
            Err(errors) => {
                return Err(Error::new(errors.to_string()));
            }
        }
    }
    Ok(())
}

fn pass_through_to_actual_compiler() {
    let args: Vec<_> = std::env::args().skip(2).collect();
    std::process::Command::new("rustc")
        .args(args)
        .status()
        .expect("Failed to run rustc");
}

pub fn main() {
    let driver = RerastCompilerDriver::new(ArgBuilder::from_args(std::env::args().skip(1)));
    if let Ok(_) = std::env::var(var_names::PRINT_ARGS_JSON) {
        // If cargo is calling us to get compiler configuration or is compiling
        // a dependent crate, thenp just run the compiler normally.
        if driver.args().has_arg("--print=cfg") || driver.is_compiling_dependency() {
            pass_through_to_actual_compiler();
        } else {
            let json_args: Vec<JsonValue> =
                std::env::args().map(|a| JsonValue::String(a)).collect();
            println!("{}{}", JSON_ARGS_MARKER, JsonValue::Array(json_args).dump());
            pass_through_to_actual_compiler();
        }
    } else {
        if let Err(error) = cargo_rerast() {
            eprintln!("{}", error.message);
        }
    }
}
<|endoftext|>


<commit_before>use super::DELIMITER;
use super::super::ledger::request::ProtocolVersion;

use ursa::cl::{
    CredentialPrimaryPublicKey,
    CredentialRevocationPublicKey,
    CredentialPrivateKey,
    CredentialKeyCorrectnessProof
};

use std::collections::HashMap;
use named_type::NamedType;

pub const CL_SIGNATURE_TYPE: &str = "CL";
pub const CRED_DEF_MARKER: &str = "3";

#[derive(Deserialize, Debug, Serialize, PartialEq, Clone)]
pub enum SignatureType {
    CL
}

impl SignatureType {
    pub fn to_str(&self) -> &'static str {
        match *self {
            SignatureType::CL => CL_SIGNATURE_TYPE
        }
    }
}

fn default_false() -> bool { false }

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CredentialDefinitionConfig {
    #[serde(default = "default_false")]
    pub support_revocation: bool
}

impl Default for CredentialDefinitionConfig {
    fn default() -> Self {
        CredentialDefinitionConfig {
            support_revocation: false
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CredentialDefinitionData {
    pub primary: CredentialPrimaryPublicKey,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub revocation: Option<CredentialRevocationPublicKey>
}

#[derive(Deserialize, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CredentialDefinitionV1 {
    pub id: String,
    pub schema_id: String,
    #[serde(rename = "type")]
    pub signature_type: SignatureType,
    pub tag: String,
    pub value: CredentialDefinitionData
}

#[derive(Debug, Serialize, Deserialize, NamedType)]
#[serde(tag = "ver")]
pub enum CredentialDefinition {
    #[serde(rename = "1.0")]
    CredentialDefinitionV1(CredentialDefinitionV1)
}

impl CredentialDefinition {
    pub fn cred_def_id(did: &str, schema_id: &str, signature_type: &str, tag: &str) -> String {
        if ProtocolVersion::is_node_1_3(){
            format!("{}{}{}{}{}{}{}", did, DELIMITER, CRED_DEF_MARKER, DELIMITER, signature_type, DELIMITER, schema_id)
        } else {
            format!("{}{}{}{}{}{}{}{}{}", did, DELIMITER, CRED_DEF_MARKER, DELIMITER, signature_type, DELIMITER, schema_id, DELIMITER, tag)
        }
    }

    pub fn issuer_did(cred_def_id: &str) -> Option<String> {
        cred_def_id.split(":").collect::<Vec<&str>>().get(0).and_then(|s| Some(s.to_string()))
    }
}

impl From<CredentialDefinition> for CredentialDefinitionV1 {
    fn from(cred_def: CredentialDefinition) -> Self {
        match cred_def {
            CredentialDefinition::CredentialDefinitionV1(cred_def) => cred_def
        }
    }
}

pub fn cred_defs_map_to_cred_defs_v1_map(cred_defs: HashMap<String, CredentialDefinition>) -> HashMap<String, CredentialDefinitionV1> {
    let mut cred_defs_v1: HashMap<String, CredentialDefinitionV1> = HashMap::new();

    for (cred_def_id, cred_def) in cred_defs {
        cred_defs_v1.insert(cred_def_id, CredentialDefinitionV1::from(cred_def));
    }

    cred_defs_v1
}

#[derive(Debug, Serialize, Deserialize, NamedType)]
pub struct CredentialDefinitionPrivateKey {
    pub value: CredentialPrivateKey
}

#[derive(Debug, Serialize, Deserialize, NamedType)]
pub struct CredentialDefinitionCorrectnessProof {
    pub value: CredentialKeyCorrectnessProof
}
<commit_msg>replace single char str by single char char<commit_after>use super::DELIMITER;
use super::super::ledger::request::ProtocolVersion;

use ursa::cl::{
    CredentialPrimaryPublicKey,
    CredentialRevocationPublicKey,
    CredentialPrivateKey,
    CredentialKeyCorrectnessProof
};

use std::collections::HashMap;
use named_type::NamedType;

pub const CL_SIGNATURE_TYPE: &str = "CL";
pub const CRED_DEF_MARKER: &str = "3";

#[derive(Deserialize, Debug, Serialize, PartialEq, Clone)]
pub enum SignatureType {
    CL
}

impl SignatureType {
    pub fn to_str(&self) -> &'static str {
        match *self {
            SignatureType::CL => CL_SIGNATURE_TYPE
        }
    }
}

fn default_false() -> bool { false }

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CredentialDefinitionConfig {
    #[serde(default = "default_false")]
    pub support_revocation: bool
}

impl Default for CredentialDefinitionConfig {
    fn default() -> Self {
        CredentialDefinitionConfig {
            support_revocation: false
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CredentialDefinitionData {
    pub primary: CredentialPrimaryPublicKey,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub revocation: Option<CredentialRevocationPublicKey>
}

#[derive(Deserialize, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CredentialDefinitionV1 {
    pub id: String,
    pub schema_id: String,
    #[serde(rename = "type")]
    pub signature_type: SignatureType,
    pub tag: String,
    pub value: CredentialDefinitionData
}

#[derive(Debug, Serialize, Deserialize, NamedType)]
#[serde(tag = "ver")]
pub enum CredentialDefinition {
    #[serde(rename = "1.0")]
    CredentialDefinitionV1(CredentialDefinitionV1)
}

impl CredentialDefinition {
    pub fn cred_def_id(did: &str, schema_id: &str, signature_type: &str, tag: &str) -> String {
        if ProtocolVersion::is_node_1_3(){
            format!("{}{}{}{}{}{}{}", did, DELIMITER, CRED_DEF_MARKER, DELIMITER, signature_type, DELIMITER, schema_id)
        } else {
            format!("{}{}{}{}{}{}{}{}{}", did, DELIMITER, CRED_DEF_MARKER, DELIMITER, signature_type, DELIMITER, schema_id, DELIMITER, tag)
        }
    }

    pub fn issuer_did(cred_def_id: &str) -> Option<String> {
        cred_def_id.split(':').collect::<Vec<&str>>().get(0).and_then(|s| Some(s.to_string()))
    }
}

impl From<CredentialDefinition> for CredentialDefinitionV1 {
    fn from(cred_def: CredentialDefinition) -> Self {
        match cred_def {
            CredentialDefinition::CredentialDefinitionV1(cred_def) => cred_def
        }
    }
}

pub fn cred_defs_map_to_cred_defs_v1_map(cred_defs: HashMap<String, CredentialDefinition>) -> HashMap<String, CredentialDefinitionV1> {
    let mut cred_defs_v1: HashMap<String, CredentialDefinitionV1> = HashMap::new();

    for (cred_def_id, cred_def) in cred_defs {
        cred_defs_v1.insert(cred_def_id, CredentialDefinitionV1::from(cred_def));
    }

    cred_defs_v1
}

#[derive(Debug, Serialize, Deserialize, NamedType)]
pub struct CredentialDefinitionPrivateKey {
    pub value: CredentialPrivateKey
}

#[derive(Debug, Serialize, Deserialize, NamedType)]
pub struct CredentialDefinitionCorrectnessProof {
    pub value: CredentialKeyCorrectnessProof
}
<|endoftext|>


<commit_before>use crate::command_prelude::*;
use crate::util::restricted_names::is_glob_pattern;
use crate::util::ProcessError;
use cargo::core::Verbosity;
use cargo::ops::{self, CompileFilter, Packages};

pub fn cli() -> App {
    subcommand("run")
        // subcommand aliases are handled in aliased_command()
        // .alias("r")
        .setting(AppSettings::TrailingVarArg)
        .about("Run a binary or example of the local package")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(Arg::with_name("args").multiple(true))
        .arg_targets_bin_example(
            "Name of the bin target to run",
            "Name of the example target to run",
        )
        .arg_package("Package with the target to run")
        .arg_jobs()
        .arg_release("Build artifacts in release mode, with optimizations")
        .arg_profile("Build artifacts with the specified profile")
        .arg_features()
        .arg_target_triple("Build for the target triple")
        .arg_target_dir()
        .arg_manifest_path()
        .arg_message_format()
        .arg_unit_graph()
        .after_help("Run `cargo help run` for more detailed information.\n")
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;

    let mut compile_opts = args.compile_options(
        config,
        CompileMode::Build,
        Some(&ws),
        ProfileChecking::Checked,
    )?;

    // Disallow `spec` to be an glob pattern
    match &compile_opts.spec {
        Packages::Packages(opt_in) => {
            if let Some(pattern) = opt_in.iter().find(|s| is_glob_pattern(s)) {
                return Err(anyhow::anyhow!(
                    "`cargo run` does not support glob pattern `{}` on package selection",
                    pattern,
                )
                .into());
            }
        }
        _ => (),
    }

    if !args.is_present("example") && !args.is_present("bin") {
        let default_runs: Vec<_> = compile_opts
            .spec
            .get_packages(&ws)?
            .iter()
            .filter_map(|pkg| pkg.manifest().default_run())
            .collect();
        if default_runs.len() == 1 {
            compile_opts.filter = CompileFilter::from_raw_arguments(
                false,
                vec![default_runs[0].to_owned()],
                false,
                vec![],
                false,
                vec![],
                false,
                vec![],
                false,
                false,
            );
        } else {
            // ops::run will take care of errors if len pkgs != 1.
            compile_opts.filter = CompileFilter::Default {
                // Force this to false because the code in ops::run is not
                // able to pre-check features before compilation starts to
                // enforce that only 1 binary is built.
                required_features_filterable: false,
            };
        }
    };

    ops::run(&ws, &compile_opts, &values_os(args, "args")).map_err(|err| {
        let proc_err = match err.downcast_ref::<ProcessError>() {
            Some(e) => e,
            None => return CliError::new(err, 101),
        };

        // If we never actually spawned the process then that sounds pretty
        // bad and we always want to forward that up.
        let exit = match proc_err.exit {
            Some(exit) => exit,
            None => return CliError::new(err, 101),
        };

        // If `-q` was passed then we suppress extra error information about
        // a failed process, we assume the process itself printed out enough
        // information about why it failed so we don't do so as well
        let exit_code = exit.code().unwrap_or(101);
        let is_quiet = config.shell().verbosity() == Verbosity::Quiet;
        if is_quiet {
            CliError::code(exit_code)
        } else {
            CliError::new(err, exit_code)
        }
    })
}
<commit_msg>refactor: simplify match -> if let<commit_after>use crate::command_prelude::*;
use crate::util::restricted_names::is_glob_pattern;
use crate::util::ProcessError;
use cargo::core::Verbosity;
use cargo::ops::{self, CompileFilter, Packages};

pub fn cli() -> App {
    subcommand("run")
        // subcommand aliases are handled in aliased_command()
        // .alias("r")
        .setting(AppSettings::TrailingVarArg)
        .about("Run a binary or example of the local package")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(Arg::with_name("args").multiple(true))
        .arg_targets_bin_example(
            "Name of the bin target to run",
            "Name of the example target to run",
        )
        .arg_package("Package with the target to run")
        .arg_jobs()
        .arg_release("Build artifacts in release mode, with optimizations")
        .arg_profile("Build artifacts with the specified profile")
        .arg_features()
        .arg_target_triple("Build for the target triple")
        .arg_target_dir()
        .arg_manifest_path()
        .arg_message_format()
        .arg_unit_graph()
        .after_help("Run `cargo help run` for more detailed information.\n")
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;

    let mut compile_opts = args.compile_options(
        config,
        CompileMode::Build,
        Some(&ws),
        ProfileChecking::Checked,
    )?;

    // Disallow `spec` to be an glob pattern
    if let Packages::Packages(opt_in) = &compile_opts.spec {
        if let Some(pattern) = opt_in.iter().find(|s| is_glob_pattern(s)) {
            return Err(anyhow::anyhow!(
                "`cargo run` does not support glob pattern `{}` on package selection",
                pattern,
            )
            .into());
        }
    }

    if !args.is_present("example") && !args.is_present("bin") {
        let default_runs: Vec<_> = compile_opts
            .spec
            .get_packages(&ws)?
            .iter()
            .filter_map(|pkg| pkg.manifest().default_run())
            .collect();
        if default_runs.len() == 1 {
            compile_opts.filter = CompileFilter::from_raw_arguments(
                false,
                vec![default_runs[0].to_owned()],
                false,
                vec![],
                false,
                vec![],
                false,
                vec![],
                false,
                false,
            );
        } else {
            // ops::run will take care of errors if len pkgs != 1.
            compile_opts.filter = CompileFilter::Default {
                // Force this to false because the code in ops::run is not
                // able to pre-check features before compilation starts to
                // enforce that only 1 binary is built.
                required_features_filterable: false,
            };
        }
    };

    ops::run(&ws, &compile_opts, &values_os(args, "args")).map_err(|err| {
        let proc_err = match err.downcast_ref::<ProcessError>() {
            Some(e) => e,
            None => return CliError::new(err, 101),
        };

        // If we never actually spawned the process then that sounds pretty
        // bad and we always want to forward that up.
        let exit = match proc_err.exit {
            Some(exit) => exit,
            None => return CliError::new(err, 101),
        };

        // If `-q` was passed then we suppress extra error information about
        // a failed process, we assume the process itself printed out enough
        // information about why it failed so we don't do so as well
        let exit_code = exit.code().unwrap_or(101);
        let is_quiet = config.shell().verbosity() == Verbosity::Quiet;
        if is_quiet {
            CliError::code(exit_code)
        } else {
            CliError::new(err, exit_code)
        }
    })
}
<|endoftext|>


<commit_before>use std::io::{Result, Write};

use analysis;
use analysis::bounds::Bounds;
use analysis::functions::Visibility;
use analysis::namespaces;
use chunk::{ffi_function_todo, Chunk};
use env::Env;
use super::function_body_chunk;
use super::general::{cfg_condition, doc_hidden, not_version_condition, version_condition};
use super::parameter::ToParameter;
use super::return_value::{out_parameters_as_return, ToReturnValue};
use writer::primitives::tabs;
use writer::ToCode;
use library;

pub fn generate(w: &mut Write, env: &Env, analysis: &analysis::functions::Info,
                in_trait: bool, only_declaration: bool, indent: usize) -> Result<()> {
    let mut commented = false;
    let mut comment_prefix = "";
    let mut pub_prefix = if in_trait { "" } else { "pub " };
    match analysis.visibility {
        Visibility::Public => {}
        Visibility::Comment => {
            commented = true;
            comment_prefix = "//";
        }
        Visibility::Private => {
            if in_trait {
                warn!("Generating trait method for private function {}", analysis.glib_name);
            }
            else {
                pub_prefix = "";
            }
        }
        Visibility::Hidden => return Ok(()),
    }
    let declaration = declaration(env, analysis);
    let suffix = if only_declaration { ";" } else { " {" };

    try!(writeln!(w, ""));
    try!(cfg_condition(w, &analysis.cfg_condition, commented, indent));
    try!(version_condition(w, env, analysis.version, commented, indent));
    try!(not_version_condition(w, analysis.not_version, commented, indent));
    try!(doc_hidden(w, analysis.doc_hidden, comment_prefix, indent));
    try!(writeln!(w, "{}{}{}{}{}", tabs(indent),
        comment_prefix, pub_prefix, declaration, suffix));

    if !only_declaration {
        let body = body_chunk(env, analysis).to_code(env);
        for s in body {
            try!(writeln!(w, "{}{}", tabs(indent), s));
        }
    }

    Ok(())
}

pub fn declaration(env: &Env, analysis: &analysis::functions::Info) -> String {
    let outs_as_return = !analysis.outs.is_empty();
    let return_str = if outs_as_return {
        out_parameters_as_return(env, analysis)
    } else if analysis.ret.bool_return_is_error.is_some() {
        if env.namespaces.glib_ns_id == namespaces::MAIN {
            " -> Result<(), error::BoolError>".into()
        } else {
            " -> Result<(), glib::error::BoolError>".into()
        }
    } else {
        analysis.ret.to_return_value(env)
    };
    let mut param_str = String::with_capacity(100);

    let bounds = bounds(&analysis.bounds);

    let array_lengths: Vec<_> = analysis.parameters.iter()
                                                    .filter_map(|p| p.array_length)
                                                    .collect();

    let mut skipped = 0;
    for (pos, par) in analysis.parameters.iter().enumerate() {
        if outs_as_return && analysis.outs.iter().any(|p| p.name==par.name) {
            skipped += 1;
            continue;
        }

        // The first parameter is &self in case of methods
        let pos_offset = if analysis.kind == library::FunctionKind::Method { 1 } else { 0 };
        if pos >= pos_offset && array_lengths.contains(&((pos - pos_offset) as u32)) {
            skipped += 1;
            continue;
        }

        if pos > skipped { param_str.push_str(", ") }
        let s = par.to_parameter(env, &analysis.bounds);
        param_str.push_str(&s);
    }

    format!("fn {}{}({}){}", analysis.name, bounds, param_str, return_str)
}

pub fn bounds(bounds: &Bounds) -> String {
    use analysis::bounds::BoundType::*;
    if bounds.is_empty() { return String::new() }
    let strs: Vec<String> = bounds.iter_lifetimes()
        .map(|s| format!("'{}", s))
        .chain(bounds.iter()
                     .map(|bound| match bound.bound_type {
                         IsA(Some(lifetime)) => format!("{}: IsA<{}> + '{}",
                                                        bound.alias, bound.type_str, lifetime),
                         IsA(None) => format!("{}: IsA<{}>", bound.alias, bound.type_str),
                         // This case should normally never happened
                         AsRef(Some(lifetime)) => format!("{}: AsRef<{}> + '{}",
                                                          bound.alias, bound.type_str, lifetime),
                         AsRef(None) => format!("{}: AsRef<{}>", bound.alias, bound.type_str),
                         Into(Some(l), _) => format!("{}: Into<Option<&'{} {}>>",
                                                     bound.alias, l, bound.type_str),
                         Into(None, _) => format!("{}: Into<Option<{}>>",
                                                  bound.alias, bound.type_str),
                     }))
        .collect();
    format!("<{}>", strs.join(", "))
}

pub fn body_chunk(env: &Env, analysis: &analysis::functions::Info) -> Chunk {
    if analysis.visibility == Visibility::Comment {
        return ffi_function_todo(&analysis.glib_name);
    }

    let outs_as_return = !analysis.outs.is_empty();
    let ret_array_length = if let Some(pos) = analysis.ret.parameter.as_ref().and_then(|p| p.array_length) {
        // The first parameter is &self in case of methods
        let pos_offset = if analysis.kind == library::FunctionKind::Method { 1 } else { 0 };
        analysis.parameters.iter().nth((pos + pos_offset) as usize)
    } else {
        None
    };

    let mut builder = function_body_chunk::Builder::new();
    builder.glib_name(&analysis.glib_name)
        .assertion(analysis.assertion)
        .ret(env, &analysis.ret, ret_array_length)
        .outs_mode(analysis.outs.mode);

    for par in &analysis.parameters {
        if outs_as_return && analysis.outs.iter().any(|p| p.name==par.name) {
            let array_length = if let Some(pos) = par.array_length {
                use analysis::out_parameters::Mode;
                // The actual return value was inserted at position 0
                let pos_offset = if analysis.outs.mode == Mode::Combined || analysis.outs.mode == Mode::Throws(true) { 1 } else { 0 };
                analysis.parameters.iter().nth((pos + pos_offset) as usize)
            } else {
                None
            };

            builder.out_parameter(env, par, array_length);
        } else {
            let array_length = if let Some(pos) = par.array_length {
                // The first parameter is &self in case of methods
                let pos_offset = if analysis.kind == library::FunctionKind::Method { 1 } else { 0 };
                analysis.parameters.iter().nth((pos + pos_offset) as usize)
            } else {
                None
            };

            builder.parameter(env, par, array_length);
        }
    }

    builder.generate()
}
<commit_msg>Use Vec<_>::get() instead of iter().nth()<commit_after>use std::io::{Result, Write};

use analysis;
use analysis::bounds::Bounds;
use analysis::functions::Visibility;
use analysis::namespaces;
use chunk::{ffi_function_todo, Chunk};
use env::Env;
use super::function_body_chunk;
use super::general::{cfg_condition, doc_hidden, not_version_condition, version_condition};
use super::parameter::ToParameter;
use super::return_value::{out_parameters_as_return, ToReturnValue};
use writer::primitives::tabs;
use writer::ToCode;
use library;

pub fn generate(w: &mut Write, env: &Env, analysis: &analysis::functions::Info,
                in_trait: bool, only_declaration: bool, indent: usize) -> Result<()> {
    let mut commented = false;
    let mut comment_prefix = "";
    let mut pub_prefix = if in_trait { "" } else { "pub " };
    match analysis.visibility {
        Visibility::Public => {}
        Visibility::Comment => {
            commented = true;
            comment_prefix = "//";
        }
        Visibility::Private => {
            if in_trait {
                warn!("Generating trait method for private function {}", analysis.glib_name);
            }
            else {
                pub_prefix = "";
            }
        }
        Visibility::Hidden => return Ok(()),
    }
    let declaration = declaration(env, analysis);
    let suffix = if only_declaration { ";" } else { " {" };

    try!(writeln!(w, ""));
    try!(cfg_condition(w, &analysis.cfg_condition, commented, indent));
    try!(version_condition(w, env, analysis.version, commented, indent));
    try!(not_version_condition(w, analysis.not_version, commented, indent));
    try!(doc_hidden(w, analysis.doc_hidden, comment_prefix, indent));
    try!(writeln!(w, "{}{}{}{}{}", tabs(indent),
        comment_prefix, pub_prefix, declaration, suffix));

    if !only_declaration {
        let body = body_chunk(env, analysis).to_code(env);
        for s in body {
            try!(writeln!(w, "{}{}", tabs(indent), s));
        }
    }

    Ok(())
}

pub fn declaration(env: &Env, analysis: &analysis::functions::Info) -> String {
    let outs_as_return = !analysis.outs.is_empty();
    let return_str = if outs_as_return {
        out_parameters_as_return(env, analysis)
    } else if analysis.ret.bool_return_is_error.is_some() {
        if env.namespaces.glib_ns_id == namespaces::MAIN {
            " -> Result<(), error::BoolError>".into()
        } else {
            " -> Result<(), glib::error::BoolError>".into()
        }
    } else {
        analysis.ret.to_return_value(env)
    };
    let mut param_str = String::with_capacity(100);

    let bounds = bounds(&analysis.bounds);

    let array_lengths: Vec<_> = analysis.parameters.iter()
                                                    .filter_map(|p| p.array_length)
                                                    .collect();

    let mut skipped = 0;
    for (pos, par) in analysis.parameters.iter().enumerate() {
        if outs_as_return && analysis.outs.iter().any(|p| p.name==par.name) {
            skipped += 1;
            continue;
        }

        // The first parameter is &self in case of methods
        let pos_offset = if analysis.kind == library::FunctionKind::Method { 1 } else { 0 };
        if pos >= pos_offset && array_lengths.contains(&((pos - pos_offset) as u32)) {
            skipped += 1;
            continue;
        }

        if pos > skipped { param_str.push_str(", ") }
        let s = par.to_parameter(env, &analysis.bounds);
        param_str.push_str(&s);
    }

    format!("fn {}{}({}){}", analysis.name, bounds, param_str, return_str)
}

pub fn bounds(bounds: &Bounds) -> String {
    use analysis::bounds::BoundType::*;
    if bounds.is_empty() { return String::new() }
    let strs: Vec<String> = bounds.iter_lifetimes()
        .map(|s| format!("'{}", s))
        .chain(bounds.iter()
                     .map(|bound| match bound.bound_type {
                         IsA(Some(lifetime)) => format!("{}: IsA<{}> + '{}",
                                                        bound.alias, bound.type_str, lifetime),
                         IsA(None) => format!("{}: IsA<{}>", bound.alias, bound.type_str),
                         // This case should normally never happened
                         AsRef(Some(lifetime)) => format!("{}: AsRef<{}> + '{}",
                                                          bound.alias, bound.type_str, lifetime),
                         AsRef(None) => format!("{}: AsRef<{}>", bound.alias, bound.type_str),
                         Into(Some(l), _) => format!("{}: Into<Option<&'{} {}>>",
                                                     bound.alias, l, bound.type_str),
                         Into(None, _) => format!("{}: Into<Option<{}>>",
                                                  bound.alias, bound.type_str),
                     }))
        .collect();
    format!("<{}>", strs.join(", "))
}

pub fn body_chunk(env: &Env, analysis: &analysis::functions::Info) -> Chunk {
    if analysis.visibility == Visibility::Comment {
        return ffi_function_todo(&analysis.glib_name);
    }

    let outs_as_return = !analysis.outs.is_empty();
    let ret_array_length = if let Some(pos) = analysis.ret.parameter.as_ref().and_then(|p| p.array_length) {
        // The first parameter is &self in case of methods
        let pos_offset = if analysis.kind == library::FunctionKind::Method { 1 } else { 0 };
        analysis.parameters.get((pos + pos_offset) as usize)
    } else {
        None
    };

    let mut builder = function_body_chunk::Builder::new();
    builder.glib_name(&analysis.glib_name)
        .assertion(analysis.assertion)
        .ret(env, &analysis.ret, ret_array_length)
        .outs_mode(analysis.outs.mode);

    for par in &analysis.parameters {
        if outs_as_return && analysis.outs.iter().any(|p| p.name==par.name) {
            let array_length = if let Some(pos) = par.array_length {
                use analysis::out_parameters::Mode;
                // The actual return value was inserted at position 0
                let pos_offset = if analysis.outs.mode == Mode::Combined || analysis.outs.mode == Mode::Throws(true) { 1 } else { 0 };
                analysis.parameters.get((pos + pos_offset) as usize)
            } else {
                None
            };

            builder.out_parameter(env, par, array_length);
        } else {
            let array_length = if let Some(pos) = par.array_length {
                // The first parameter is &self in case of methods
                let pos_offset = if analysis.kind == library::FunctionKind::Method { 1 } else { 0 };
                analysis.parameters.get((pos + pos_offset) as usize)
            } else {
                None
            };

            builder.parameter(env, par, array_length);
        }
    }

    builder.generate()
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Two simple cache data structures.

use rand;
use rand::Rng;
use std::hash::{Hash, Hasher, SipHasher};
use std::slice::{Iter, IterMut};

pub struct LRUCache<K, V> {
    entries: Vec<(K, V)>,
    cache_size: usize,
}

impl<K: PartialEq, V: Clone> LRUCache<K, V> {
    pub fn new(size: usize) -> LRUCache<K, V> {
        LRUCache {
          entries: vec![],
          cache_size: size,
        }
    }

    #[inline]
    pub fn touch(&mut self, pos: usize) -> &V {
        let last_index = self.entries.len() - 1;
        if pos != last_index {
            let entry = self.entries.remove(pos);
            self.entries.push(entry);
        }
        &self.entries[last_index].1
    }

    pub fn iter(&self) -> Iter<(K, V)> {
        self.entries.iter()
    }

    pub fn iter_mut(&mut self) -> IterMut<(K, V)> {
        self.entries.iter_mut()
    }

    pub fn insert(&mut self, key: K, val: V) {
        if self.entries.len() == self.cache_size {
            self.entries.remove(0);
        }
        self.entries.push((key, val));
    }

    pub fn find(&mut self, key: &K) -> Option<V> {
        match self.entries.iter().position(|&(ref k, _)| key == k) {
            Some(pos) => Some(self.touch(pos).clone()),
            None      => None,
        }
    }

    pub fn find_or_create<F>(&mut self, key: K, mut blk: F) -> V where F: FnMut() -> V {
        match self.entries.iter().position(|&(ref k, _)| *k == key) {
            Some(pos) => self.touch(pos).clone(),
            None => {
                let val = blk();
                self.insert(key, val.clone());
                val
            }
        }
    }

    pub fn evict_all(&mut self) {
        self.entries.clear();
    }
}

pub struct SimpleHashCache<K, V> {
    entries: Vec<Option<(K, V)>>,
    k0: u64,
    k1: u64,
}

impl<K: Clone + Eq + Hash, V: Clone> SimpleHashCache<K, V> {
    pub fn new(cache_size: usize) -> SimpleHashCache<K, V> {
        let mut r = rand::thread_rng();
        SimpleHashCache {
            entries: vec![None; cache_size],
            k0: r.gen(),
            k1: r.gen(),
        }
    }

    #[inline]
    fn to_bucket(&self, h: usize) -> usize {
        h % self.entries.len()
    }

    #[inline]
    fn bucket_for_key<Q: Hash>(&self, key: &Q) -> usize {
        let mut hasher = SipHasher::new_with_keys(self.k0, self.k1);
        key.hash(&mut hasher);
        self.to_bucket(hasher.finish() as usize)
    }

    pub fn insert(&mut self, key: K, value: V) {
        let bucket_index = self.bucket_for_key(&key);
        self.entries[bucket_index] = Some((key, value));
    }

    pub fn find<Q>(&self, key: &Q) -> Option<V> where Q: PartialEq<K> + Hash + Eq {
        let bucket_index = self.bucket_for_key(key);
        match self.entries[bucket_index] {
            Some((ref existing_key, ref value)) if key == existing_key => Some((*value).clone()),
            _ => None,
        }
    }

    pub fn find_or_create<F>(&mut self, key: K, mut blk: F) -> V where F: FnMut() -> V {
        if let Some(value) = self.find(&key) {
            return value;
        }
        let value = blk();
        self.insert(key, value.clone());
        value
    }

    pub fn evict_all(&mut self) {
        for slot in &mut self.entries {
            *slot = None
        }
    }
}
<commit_msg>Remove usage of deprecated `SipHasher`.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Two simple cache data structures.

use std::collections::hash_map::RandomState;
use std::hash::{Hash, Hasher, BuildHasher};
use std::slice::{Iter, IterMut};

pub struct LRUCache<K, V> {
    entries: Vec<(K, V)>,
    cache_size: usize,
}

impl<K: PartialEq, V: Clone> LRUCache<K, V> {
    pub fn new(size: usize) -> LRUCache<K, V> {
        LRUCache {
          entries: vec![],
          cache_size: size,
        }
    }

    #[inline]
    pub fn touch(&mut self, pos: usize) -> &V {
        let last_index = self.entries.len() - 1;
        if pos != last_index {
            let entry = self.entries.remove(pos);
            self.entries.push(entry);
        }
        &self.entries[last_index].1
    }

    pub fn iter(&self) -> Iter<(K, V)> {
        self.entries.iter()
    }

    pub fn iter_mut(&mut self) -> IterMut<(K, V)> {
        self.entries.iter_mut()
    }

    pub fn insert(&mut self, key: K, val: V) {
        if self.entries.len() == self.cache_size {
            self.entries.remove(0);
        }
        self.entries.push((key, val));
    }

    pub fn find(&mut self, key: &K) -> Option<V> {
        match self.entries.iter().position(|&(ref k, _)| key == k) {
            Some(pos) => Some(self.touch(pos).clone()),
            None      => None,
        }
    }

    pub fn find_or_create<F>(&mut self, key: K, mut blk: F) -> V where F: FnMut() -> V {
        match self.entries.iter().position(|&(ref k, _)| *k == key) {
            Some(pos) => self.touch(pos).clone(),
            None => {
                let val = blk();
                self.insert(key, val.clone());
                val
            }
        }
    }

    pub fn evict_all(&mut self) {
        self.entries.clear();
    }
}

pub struct SimpleHashCache<K, V> {
    entries: Vec<Option<(K, V)>>,
    random: RandomState,
}

impl<K: Clone + Eq + Hash, V: Clone> SimpleHashCache<K, V> {
    pub fn new(cache_size: usize) -> SimpleHashCache<K, V> {
        SimpleHashCache {
            entries: vec![None; cache_size],
            random: RandomState::new(),
        }
    }

    #[inline]
    fn to_bucket(&self, h: usize) -> usize {
        h % self.entries.len()
    }

    #[inline]
    fn bucket_for_key<Q: Hash>(&self, key: &Q) -> usize {
        let mut hasher = self.random.build_hasher();
        key.hash(&mut hasher);
        self.to_bucket(hasher.finish() as usize)
    }

    pub fn insert(&mut self, key: K, value: V) {
        let bucket_index = self.bucket_for_key(&key);
        self.entries[bucket_index] = Some((key, value));
    }

    pub fn find<Q>(&self, key: &Q) -> Option<V> where Q: PartialEq<K> + Hash + Eq {
        let bucket_index = self.bucket_for_key(key);
        match self.entries[bucket_index] {
            Some((ref existing_key, ref value)) if key == existing_key => Some((*value).clone()),
            _ => None,
        }
    }

    pub fn find_or_create<F>(&mut self, key: K, mut blk: F) -> V where F: FnMut() -> V {
        if let Some(value) = self.find(&key) {
            return value;
        }
        let value = blk();
        self.insert(key, value.clone());
        value
    }

    pub fn evict_all(&mut self) {
        for slot in &mut self.entries {
            *slot = None
        }
    }
}
<|endoftext|>


<commit_before>/// Generates a property definition that simply parses strings to enum variants
///
/// This can be used for properties with simple symbol-based values.
/// For example, the SVG spec defines the `stroke-linejoin` property
/// to have possible values `miter | round | bevel | inherit`, with a default
/// of `miter`.  We can define the property like this:
///
/// ```
/// make_ident_property!(
/// StrokeLinejoin,
/// default: Miter,
///
/// "miter" => Miter,
/// "round" => Round,
/// "bevel" => Bevel,
/// "inherit" => Inherit,
/// );
/// ```
///
/// The macro will generate a `StrokeLinejoin` enum with the provided
/// variants.  It will generate an `impl Default for StrokeLinejoin`
/// with the provided `default:` value.  Finally, it will generate an
/// `impl Parse for StrokeLinejoin`, from `parsers::Parse`, where
/// `type Data = ()` and `type Err = AttributeError`.
#[macro_export]
macro_rules! make_ident_property {
    ($name: ident,
     default: $default: ident,
     $($str_prop: expr => $variant: ident,)+
    ) => {
        #[derive(Debug, Copy, Clone)]
        pub enum $name {
            $($variant),+
        }

        impl Default for $name {
            fn default() -> $name {
                $name::$default
            }
        }

        impl Parse for $name {
            type Data = ();
            type Err = AttributeError;

            fn parse(s: &str, _: Self::Data) -> Result<$name, AttributeError> {
                match s.trim() {
                    $($str_prop => Ok($name::$variant),)+

                    _ => Err(AttributeError::from(ParseError::new("invalid value"))),
                }
            }
        }
    };
}
<commit_msg>property macros: enums shoould have a C representation<commit_after>/// Generates a property definition that simply parses strings to enum variants
///
/// This can be used for properties with simple symbol-based values.
/// For example, the SVG spec defines the `stroke-linejoin` property
/// to have possible values `miter | round | bevel | inherit`, with a default
/// of `miter`.  We can define the property like this:
///
/// ```
/// make_ident_property!(
/// StrokeLinejoin,
/// default: Miter,
///
/// "miter" => Miter,
/// "round" => Round,
/// "bevel" => Bevel,
/// "inherit" => Inherit,
/// );
/// ```
///
/// The macro will generate a `StrokeLinejoin` enum with the provided
/// variants.  It will generate an `impl Default for StrokeLinejoin`
/// with the provided `default:` value.  Finally, it will generate an
/// `impl Parse for StrokeLinejoin`, from `parsers::Parse`, where
/// `type Data = ()` and `type Err = AttributeError`.
#[macro_export]
macro_rules! make_ident_property {
    ($name: ident,
     default: $default: ident,
     $($str_prop: expr => $variant: ident,)+
    ) => {
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub enum $name {
            $($variant),+
        }

        impl Default for $name {
            fn default() -> $name {
                $name::$default
            }
        }

        impl Parse for $name {
            type Data = ();
            type Err = AttributeError;

            fn parse(s: &str, _: Self::Data) -> Result<$name, AttributeError> {
                match s.trim() {
                    $($str_prop => Ok($name::$variant),)+

                    _ => Err(AttributeError::from(ParseError::new("invalid value"))),
                }
            }
        }
    };
}
<|endoftext|>