<commit_before>/*
 * The MIT License
 *
 * Copyright 2016 Ahseya.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#[macro_use]
extern crate log;
extern crate env_logger;
extern crate byteorder;
extern crate getopts;

mod cookies;

use std::env;
use std::fs::File;
use std::io;
use std::io::Write;
use std::path::Path;

use getopts::Matches;
use getopts::Options;

use cookies::Cookies;

fn main() {
    env_logger::init()
        .or_else(|err| writeln!(&mut io::stderr(), "ERROR:main: logger init failed: {}", err))
        .unwrap();

    if let Some(matches) = args() {
        let files = &matches.free;
        let http_only = matches.opt_present("http_only");
        let parser = Cookies::new(http_only);
        process(&files, parser);
    }
}

fn args() -> Option<Matches> {
    let args: Vec<String> = env::args().collect();

    let mut opts = Options::new();
    opts.optflag("" , "help", "display this help and exit")
        .optflag("h", "http_only", "use #HttpOnly_ prefix")
        .parse(&args[1..])
        .map_err(|err| error!("{}", err))
        .ok()
        .and_then(|matches|
            if matches.opt_present("help") {
                println!("Usage: burntcookie [OPTION]... [FILE]...");
                println!("Parses Apple binary cookie file/s into their Netscape equivalent/s.");
                println!("{}", opts.usage("With no FILE, read standard input."));
                println!("Examples:");
                println!("burntcookie Cookies.binarycookies > cookies.txt\t\t\
                          Parse into cookies.txt");
                println!("RUST_LOG=WARN burntcookie Cookies.binarycookies\t\t\
                          With warnings");
                println!("");
                println!("Project home: http://github.com/horrorho/burnt-cookie");

                None
            } else {
                Some(matches)
            }
        )
}

fn process<P: AsRef<Path>>(paths: &[P], parser: Cookies) {
    if paths.is_empty() {
        buffer_file(&mut io::stdin())
                .and_then(|bs| parser.parse_content(&bs))
                .unwrap_or_else(|err| error!("stdin, {}", err))
    } else {
        paths.into_iter()
            .fold((), |_, p|
                File::open(p)
                    .and_then(|ref mut f| buffer_file(f))
                    .and_then(|bs| parser.parse_content(&bs))
                    .unwrap_or_else(|err| error!("{}: {}", p.as_ref().display(), err)))
    }
}

fn buffer_file<T: io::Read>(file: &mut T) -> io::Result<Vec<u8>>  {
    let mut bs: Vec<u8> = Vec::new();
    file.read_to_end(&mut bs).map(|_| bs)
}
<commit_msg>Use minor tidy.<commit_after>/*
 * The MIT License
 *
 * Copyright 2016 Ahseya.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#[macro_use]
extern crate log;
extern crate env_logger;
extern crate byteorder;
extern crate getopts;

mod cookies;

use std::env;
use std::fs::File;
use std::io;
use std::io::Write;
use std::path::Path;
use getopts::{ Options, Matches };
use cookies::Cookies;

fn main() {
    env_logger::init()
        .or_else(|err| writeln!(&mut io::stderr(), "ERROR:main: logger init failed: {}", err))
        .unwrap();

    if let Some(matches) = args() {
        let files = &matches.free;
        let http_only = matches.opt_present("http_only");
        let parser = Cookies::new(http_only);
        process(&files, parser);
    }
}

fn args() -> Option<Matches> {
    let args: Vec<String> = env::args().collect();

    let mut opts = Options::new();
    opts.optflag("" , "help", "display this help and exit")
        .optflag("h", "http_only", "use #HttpOnly_ prefix")
        .parse(&args[1..])
        .map_err(|err| error!("{}", err))
        .ok()
        .and_then(|matches|
            if matches.opt_present("help") {
                println!("Usage: burntcookie [OPTION]... [FILE]...");
                println!("Parses Apple binary cookie file/s into their Netscape equivalent/s.");
                println!("{}", opts.usage("With no FILE, read standard input."));
                println!("Examples:");
                println!("burntcookie Cookies.binarycookies > cookies.txt\t\t\
                          Parse into cookies.txt");
                println!("RUST_LOG=WARN burntcookie Cookies.binarycookies\t\t\
                          With warnings");
                println!("");
                println!("Project home: http://github.com/horrorho/burnt-cookie");

                None
            } else {
                Some(matches)
            }
        )
}

fn process<P: AsRef<Path>>(paths: &[P], parser: Cookies) {
    if paths.is_empty() {
        buffer_file(&mut io::stdin())
                .and_then(|bs| parser.parse_content(&bs))
                .unwrap_or_else(|err| error!("stdin, {}", err))
    } else {
        paths.into_iter()
            .fold((), |_, p|
                File::open(p)
                    .and_then(|ref mut f| buffer_file(f))
                    .and_then(|bs| parser.parse_content(&bs))
                    .unwrap_or_else(|err| error!("{}: {}", p.as_ref().display(), err)))
    }
}

fn buffer_file<T: io::Read>(file: &mut T) -> io::Result<Vec<u8>>  {
    let mut bs: Vec<u8> = Vec::new();
    file.read_to_end(&mut bs).map(|_| bs)
}
<|endoftext|>


<commit_before>#![allow(unused_variables, dead_code)]
#[macro_use]
extern crate r2pipe;
extern crate docopt;
extern crate rustc_serialize;
extern crate radeco_lib;
//extern crate core;

mod radeco;
mod structs;

use rustc_serialize::json;
use docopt::Docopt;
use std::process::exit;
use std::fs::{File};
use std::io::{Write, Read};

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_output: String,
    flag_version: bool,
    flag_shell: bool,
	flag_help: bool,
    arg_file: Option<String>,
	flag_from_json: bool,
	flag_json_builder: bool,
	cmd_run: bool,
}

static USAGE: &'static str = "
radeco. The radare2 decompiler.

Usage:
  radeco <file>
  radeco [options]
  radeco run [options] [<file>]
  radeco --shell <file>
  radeco --output=<output> <file>
  radeco --version

Options:
  --help                 Show this screen.
  --version              Show version.
  --shell                Run interactive prompt.
  --output=<mode>        Select output mode.
  --from-json            Run radeco based on config and information
                         from input json file. Needs an input file.
  --json-builder         Interactive shell used to build the config
                         json for radeco. When used with run, the
                         config generated is automatically used to
                         run radeco rather than dumping it to a file.
";

fn spawn_shell(bname: String) -> i32 {
	radeco::spawn_shell(bname)
}

//fn radeco_pipe(args:&Args) -> i32 {
	//let mut r = Radeco::pipe().unwrap();
	//if args.flag_shell {
		//r.shell();
	//} else {
		//println!("Running radeco via pipe");
		//// TODO get offset, function, bin info, ..
	//}
	//r.close();
	//0
//}

fn write_file(fname: String, res: String) {
	let mut file = File::create(fname).unwrap();
	file.write_all(res.as_bytes()).unwrap();
}

fn json_builder(run: bool) {
	let inp = structs::input_builder();
	let mut runner = inp.validate().unwrap();
	if !run {
		let mut name = inp.name.clone().unwrap();
		let json = json::as_pretty_json(&inp);
		let raw_json = format!("{}", json);
		name.push_str(".json");
		write_file(name, raw_json);
	} else {
		runner.run();
		runner.dump();
	}
}

fn read_json(fname: String) -> structs::Input {
	let mut raw_json = String::new();
	let _ = File::open(fname).unwrap().read_to_string(&mut raw_json);
	json::decode(&*raw_json).unwrap()
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    if args.flag_version {
        println!("Version: {:?}", VERSION);
        exit(0);
    }

	if args.flag_help {
		println!("{}", USAGE);
		exit(0);
	}

    //if args.arg_file != "" {
        //if args.arg_file == "-" {
            //exit(radeco_pipe(&args));
        //} else {
            //exit(radeco_file(&args));
        //}
    //}

	if args.flag_json_builder {
		json_builder(args.cmd_run);
	}

	if args.flag_from_json {
		if args.arg_file.is_none() {
			println!("{}", USAGE);
		}

		let inp = read_json(args.arg_file.clone().unwrap());
		let mut runner = inp.validate().unwrap();
		runner.run();
		runner.dump();
	}

	if args.flag_shell {
		if args.arg_file.is_none() {
			println!("{}", USAGE);
			exit(0);
		}
		let status = spawn_shell(args.arg_file.clone().unwrap());
		exit(status);
	}
}
<commit_msg>Add --verbose flag and reindent with tabs<commit_after>#![allow(unused_variables, dead_code)]
#[macro_use]
extern crate r2pipe;
extern crate docopt;
extern crate rustc_serialize;
extern crate radeco_lib;
//extern crate core;

mod radeco;
mod structs;

use rustc_serialize::json;
use docopt::Docopt;
use std::process::exit;
use std::fs::{File};
use std::io::{Write, Read};

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(Debug, RustcDecodable)]
struct Args {
	flag_output: String,
	flag_version: bool,
	flag_verbose: bool,
	flag_shell: bool,
	flag_help: bool,
	arg_file: Option<String>,
	flag_from_json: bool,
	flag_json_builder: bool,
	cmd_run: bool,
}

static USAGE: &'static str = "
radeco. The radare2 decompiler.

Usage:
  radeco <file>
  radeco [options] [<file>]
  radeco run [options] [<file>]
  radeco --shell <file>
  radeco --output=<output> <file>
  radeco --version
  radeco --verbose

Options:
  --help                 Show this screen.
  --version              Show version.
  --verbose              Display verbose output.
  --shell                Run interactive prompt.
  --output=<mode>        Select output mode.
  --from-json            Run radeco based on config and information
                         from input json file. Needs an input file.
  --json-builder         Interactive wizard to build the JSON config
                         file needed for radeco. When used with run, the
                         config generated is automatically used to
                         run radeco rather than dumping it to a file.
";

fn spawn_shell(bname: String) -> i32 {
	radeco::spawn_shell(bname)
}

//fn radeco_pipe(args:&Args) -> i32 {
	//let mut r = Radeco::pipe().unwrap();
	//if args.flag_shell {
		//r.shell();
	//} else {
		//println!("Running radeco via pipe");
		//// TODO get offset, function, bin info, ..
	//}
	//r.close();
	//0
//}

fn write_file(fname: String, res: String) {
	let mut file = File::create(fname).unwrap();
	file.write_all(res.as_bytes()).unwrap();
}

fn json_builder(run: bool) {
	let inp = structs::input_builder();
	let mut runner = inp.validate().unwrap();
	if !run {
		let mut name = inp.name.clone().unwrap();
		let json = json::as_pretty_json(&inp);
		let raw_json = format!("{}", json);
		name.push_str(".json");
		write_file(name, raw_json);
	} else {
		runner.run();
		runner.dump();
	}
}

fn read_json(fname: String) -> structs::Input {
	let mut raw_json = String::new();
	let _ = File::open(fname).unwrap().read_to_string(&mut raw_json);
	json::decode(&*raw_json).unwrap()
}

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

	if args.flag_version {
		println!("Version: {:?}", VERSION);
		exit(0);
	}

	if args.flag_help {
		println!("{}", USAGE);
		exit(0);
	}

	//if args.arg_file != "" {
		//if args.arg_file == "-" {
			//exit(radeco_pipe(&args));
		//} else {
			//exit(radeco_file(&args));
		//}
	//}

	if args.flag_json_builder {
		json_builder(args.cmd_run);
	}

	if args.flag_from_json {
		if args.arg_file.is_none() {
			println!("{}", USAGE);
		}
		let inp = read_json(args.arg_file.clone().unwrap());
		let mut runner = inp.validate().unwrap();
		runner.run();
		runner.dump();
	}

	if args.flag_shell {
		if args.arg_file.is_none() {
			println!("{}", USAGE);
			exit(0);
		}
		let status = spawn_shell(args.arg_file.clone().unwrap());
		exit(status);
	}
}
<|endoftext|>


<commit_before>//! An ultra-light private math library to make our short lives easier as we
//! implement super-complex noise stuff.

use std::ops::{Add, Mul, Sub};

/// Cast a numeric type without having to unwrap - we don't expect any overflow
/// errors...
#[inline]
pub fn cast<T, U: From<T>>(x: T) -> U {
    From::from(x)
}

/// A 2-dimensional point. This is a fixed sized array, so should be compatible
/// with most linear algebra libraries.
pub type Point2<T> = [T; 2];

/// A 3-dimensional point. This is a fixed sized array, so should be compatible
/// with most linear algebra libraries.
pub type Point3<T> = [T; 3];

/// A 4-dimensional point. This is a fixed sized array, so should be compatible
/// with most linear algebra libraries.
pub type Point4<T> = [T; 4];

/// A 2-dimensional vector, for internal use.
pub type Vector2<T> = [T; 2];
/// A 3-dimensional vector, for internal use.
pub type Vector3<T> = [T; 3];
/// A 4-dimensional vector, for internal use.
pub type Vector4<T> = [T; 4];

#[inline]
pub fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T {
    assert!(max >= min);
    match () {
        _ if val < min => min,
        _ if val > max => max,
        _ => val,
    }
}

#[inline]
pub fn map2<T, U, F>(a: Vector2<T>, f: F) -> Vector2<U>
where
    T: Copy,
    F: Fn(T) -> U,
{
    let (ax, ay) = (a[0], a[1]);
    [f(ax), f(ay)]
}

#[inline]
pub fn map3<T, U, F>(a: Vector3<T>, f: F) -> Vector3<U>
where
    T: Copy,
    F: Fn(T) -> U,
{
    let (ax, ay, az) = (a[0], a[1], a[2]);
    [f(ax), f(ay), f(az)]
}

#[inline]
pub fn map4<T, U, F>(a: Vector4<T>, f: F) -> Vector4<U>
where
    T: Copy,
    F: Fn(T) -> U,
{
    let (ax, ay, az, aw) = (a[0], a[1], a[2], a[3]);
    [f(ax), f(ay), f(az), f(aw)]
}

#[inline]
pub fn zip_with2<T, U, V, F>(a: Vector2<T>, b: Vector2<U>, f: F) -> Vector2<V>
where
    T: Copy,
    U: Copy,
    F: Fn(T, U) -> V,
{
    let (ax, ay) = (a[0], a[1]);
    let (bx, by) = (b[0], b[1]);
    [f(ax, bx), f(ay, by)]
}

#[inline]
pub fn zip_with3<T, U, V, F>(a: Vector3<T>, b: Vector3<U>, f: F) -> Vector3<V>
where
    T: Copy,
    U: Copy,
    F: Fn(T, U) -> V,
{
    let (ax, ay, az) = (a[0], a[1], a[2]);
    let (bx, by, bz) = (b[0], b[1], b[2]);
    [f(ax, bx), f(ay, by), f(az, bz)]
}

#[inline]
pub fn zip_with4<T, U, V, F>(a: Vector4<T>, b: Vector4<U>, f: F) -> Vector4<V>
where
    T: Copy,
    U: Copy,
    F: Fn(T, U) -> V,
{
    let (ax, ay, az, aw) = (a[0], a[1], a[2], a[3]);
    let (bx, by, bz, bw) = (b[0], b[1], b[2], b[3]);
    [f(ax, bx), f(ay, by), f(az, bz), f(aw, bw)]
}

#[inline]
pub fn fold2<T, F>(a: Vector2<T>, f: F) -> T
where
    T: Copy,
    F: Fn(T, T) -> T,
{
    let (ax, ay) = (a[0], a[1]);
    f(ax, ay)
}

#[inline]
pub fn fold3<T, F>(a: Vector3<T>, f: F) -> T
where
    T: Copy,
    F: Fn(T, T) -> T,
{
    let (ax, ay, az) = (a[0], a[1], a[2]);
    f(f(ax, ay), az)
}

#[inline]
pub fn fold4<T, F>(a: Vector4<T>, f: F) -> T
where
    T: Copy,
    F: Fn(T, T) -> T,
{
    let (ax, ay, az, aw) = (a[0], a[1], a[2], a[3]);
    f(f(f(ax, ay), az), aw)
}

#[inline]
pub fn add2<T>(a: Point2<T>, b: Vector2<T>) -> Point2<T>
where
    T: Copy + Add<T, Output = T>,
{
    zip_with2(a, b, Add::add)
}

#[inline]
pub fn add3<T>(a: Point3<T>, b: Vector3<T>) -> Point3<T>
where
    T: Copy + Add<T, Output = T>,
{
    zip_with3(a, b, Add::add)
}

#[inline]
pub fn add4<T>(a: Point4<T>, b: Vector4<T>) -> Point4<T>
where
    T: Copy + Add<T, Output = T>,
{
    zip_with4(a, b, Add::add)
}

#[inline]
pub fn sub2<T>(a: Point2<T>, b: Point2<T>) -> Vector2<T>
where
    T: Copy + Sub<T, Output = T>,
{
    zip_with2(a, b, Sub::sub)
}

#[inline]
pub fn sub3<T>(a: Point3<T>, b: Point3<T>) -> Vector3<T>
where
    T: Copy + Sub<T, Output = T>,
{
    zip_with3(a, b, Sub::sub)
}

#[inline]
pub fn sub4<T>(a: Point4<T>, b: Point4<T>) -> Vector4<T>
where
    T: Copy + Sub<T, Output = T>,
{
    zip_with4(a, b, Sub::sub)
}

#[inline]
pub fn mul2<T>(a: Vector2<T>, b: T) -> Vector2<T>
where
    T: Copy + Mul<T, Output = T>,
{
    zip_with2(a, const2(b), Mul::mul)
}

#[inline]
pub fn mul3<T>(a: Vector3<T>, b: T) -> Vector3<T>
where
    T: Copy + Mul<T, Output = T>,
{
    zip_with3(a, const3(b), Mul::mul)
}

#[inline]
pub fn mul4<T>(a: Vector4<T>, b: T) -> Vector4<T>
where
    T: Copy + Mul<T, Output = T>,
{
    zip_with4(a, const4(b), Mul::mul)
}

#[inline]
pub fn dot2(a: Vector2<f64>, b: Vector2<f64>) -> f64 {
    fold2(zip_with2(a, b, Mul::mul), Add::add)
}

#[inline]
pub fn dot3(a: Vector3<f64>, b: Vector3<f64>) -> f64 {
    fold3(zip_with3(a, b, Mul::mul), Add::add)
}

#[inline]
pub fn dot4(a: Vector4<f64>, b: Vector4<f64>) -> f64 {
    fold4(zip_with4(a, b, Mul::mul), Add::add)
}

#[inline]
pub fn const2<T: Copy>(x: T) -> Vector2<T> {
    [x, x]
}

#[inline]
pub fn const3<T: Copy>(x: T) -> Vector3<T> {
    [x, x, x]
}

#[inline]
pub fn const4<T: Copy>(x: T) -> Vector4<T> {
    [x, x, x, x]
}

#[inline]
pub fn one2<T: Copy + From<i8>>() -> Vector2<T> {
    cast2(const2(1))
}

#[inline]
pub fn one3<T: Copy + From<i8>>() -> Vector3<T> {
    cast3(const3(1))
}

#[inline]
pub fn one4<T: Copy + From<i8>>() -> Vector4<T> {
    cast4(const4(1))
}

#[inline]
pub fn cast2<T, U>(x: Point2<T>) -> Point2<U>
where
    T: Copy,
    U: Copy + From<T>,
{
    map2(x, cast)
}

#[inline]
pub fn cast3<T, U>(x: Point3<T>) -> Point3<U>
where
    T: Copy,
    U: Copy + From<T>,
{
    map3(x, cast)
}

#[inline]
pub fn cast4<T, U>(x: Point4<T>) -> Point4<U>
where
    T: Copy,
    U: Copy + From<T>,
{
    map4(x, cast)
}

// f64 doesn't implement From<isize>
#[inline]
pub fn to_f642(x: Point2<isize>) -> Point2<f64> {
    [x[0] as f64, x[1] as f64]
}

#[inline]
pub fn to_f643(x: Point3<isize>) -> Point3<f64> {
    [x[0] as f64, x[1] as f64, x[2] as f64]
}

#[inline]
pub fn to_f644(x: Point4<isize>) -> Point4<f64> {
    [x[0] as f64, x[1] as f64, x[2] as f64, x[3] as f64]
}

// isize doesn't implement From<f64>
#[inline]
pub fn to_isize2(x: Point2<f64>) -> Point2<isize> {
    [x[0] as isize, x[1] as isize]
}

#[cfg(not(target_os = "emscripten"))]
#[inline]
pub fn scale_shift(value: f64, n: f64) -> f64 {
    value.abs().mul_add(n, -1.0_f64)
}

#[cfg(target_os = "emscripten")]
#[inline]
pub fn scale_shift(value: f64, n: f64) -> f64 {
    (value.abs() * n) + -1.0_f64
}

#[inline]
pub fn to_isize3(x: Point3<f64>) -> Point3<isize> {
    [x[0] as isize, x[1] as isize, x[2] as isize]
}

#[inline]
pub fn to_isize4(x: Point4<f64>) -> Point4<isize> {
    [x[0] as isize, x[1] as isize, x[2] as isize, x[3] as isize]
}

pub mod interp {
    /// Performs linear interploation between two values.
    #[cfg(not(target_os = "emscripten"))]
    #[inline]
    pub fn linear(a: f64, b: f64, x: f64) -> f64 {
        x.mul_add(b - a, a)
    }

    /// Performs linear interploation between two values.
    #[cfg(target_os = "emscripten")]
    #[inline]
    pub fn linear(a: f64, b: f64, x: f64) -> f64 {
        (x * (b - a)) + a
    }

    /// Performs cubic interpolation between two values bound between two other
    /// values.
    ///
    /// - n0 - The value before the first value.
    /// - n1 - The first value.
    /// - n2 - The second value.
    /// - n3 - The value after the second value.
    /// - x - The alpha value.
    ///
    /// The alpha value should range from 0.0 to 1.0. If the alpha value is
    /// 0.0, this function returns _n1_. If the alpha value is 1.0, this
    /// function returns _n2_.
    #[inline]
    pub fn cubic(n0: f64, n1: f64, n2: f64, n3: f64, x: f64) -> f64 {
        let p = (n3 - n2) - (n0 - n1);
        let q = (n0 - n1) - p;
        let r = n2 - n0;
        let s = n1;
        p * x * x * x + q * x * x + r * x + s
    }

    /// Maps a value onto a cubic S-curve.
    #[inline]
    pub fn s_curve3(x: f64) -> f64 {
        x * x * (3.0 - (x * 2.0))
    }

    /// Maps a value onto a quintic S-curve.
    #[inline]
    pub fn s_curve5(x: f64) -> f64 {
        x * x * x * (x * (x * 6.0 - 15.0 + 10.0))
    }
}
<commit_msg>Fix bug in quintic interpolation function<commit_after>//! An ultra-light private math library to make our short lives easier as we
//! implement super-complex noise stuff.

use std::ops::{Add, Mul, Sub};

/// Cast a numeric type without having to unwrap - we don't expect any overflow
/// errors...
#[inline]
pub fn cast<T, U: From<T>>(x: T) -> U {
    From::from(x)
}

/// A 2-dimensional point. This is a fixed sized array, so should be compatible
/// with most linear algebra libraries.
pub type Point2<T> = [T; 2];

/// A 3-dimensional point. This is a fixed sized array, so should be compatible
/// with most linear algebra libraries.
pub type Point3<T> = [T; 3];

/// A 4-dimensional point. This is a fixed sized array, so should be compatible
/// with most linear algebra libraries.
pub type Point4<T> = [T; 4];

/// A 2-dimensional vector, for internal use.
pub type Vector2<T> = [T; 2];
/// A 3-dimensional vector, for internal use.
pub type Vector3<T> = [T; 3];
/// A 4-dimensional vector, for internal use.
pub type Vector4<T> = [T; 4];

#[inline]
pub fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T {
    assert!(max >= min);
    match () {
        _ if val < min => min,
        _ if val > max => max,
        _ => val,
    }
}

#[inline]
pub fn map2<T, U, F>(a: Vector2<T>, f: F) -> Vector2<U>
where
    T: Copy,
    F: Fn(T) -> U,
{
    let (ax, ay) = (a[0], a[1]);
    [f(ax), f(ay)]
}

#[inline]
pub fn map3<T, U, F>(a: Vector3<T>, f: F) -> Vector3<U>
where
    T: Copy,
    F: Fn(T) -> U,
{
    let (ax, ay, az) = (a[0], a[1], a[2]);
    [f(ax), f(ay), f(az)]
}

#[inline]
pub fn map4<T, U, F>(a: Vector4<T>, f: F) -> Vector4<U>
where
    T: Copy,
    F: Fn(T) -> U,
{
    let (ax, ay, az, aw) = (a[0], a[1], a[2], a[3]);
    [f(ax), f(ay), f(az), f(aw)]
}

#[inline]
pub fn zip_with2<T, U, V, F>(a: Vector2<T>, b: Vector2<U>, f: F) -> Vector2<V>
where
    T: Copy,
    U: Copy,
    F: Fn(T, U) -> V,
{
    let (ax, ay) = (a[0], a[1]);
    let (bx, by) = (b[0], b[1]);
    [f(ax, bx), f(ay, by)]
}

#[inline]
pub fn zip_with3<T, U, V, F>(a: Vector3<T>, b: Vector3<U>, f: F) -> Vector3<V>
where
    T: Copy,
    U: Copy,
    F: Fn(T, U) -> V,
{
    let (ax, ay, az) = (a[0], a[1], a[2]);
    let (bx, by, bz) = (b[0], b[1], b[2]);
    [f(ax, bx), f(ay, by), f(az, bz)]
}

#[inline]
pub fn zip_with4<T, U, V, F>(a: Vector4<T>, b: Vector4<U>, f: F) -> Vector4<V>
where
    T: Copy,
    U: Copy,
    F: Fn(T, U) -> V,
{
    let (ax, ay, az, aw) = (a[0], a[1], a[2], a[3]);
    let (bx, by, bz, bw) = (b[0], b[1], b[2], b[3]);
    [f(ax, bx), f(ay, by), f(az, bz), f(aw, bw)]
}

#[inline]
pub fn fold2<T, F>(a: Vector2<T>, f: F) -> T
where
    T: Copy,
    F: Fn(T, T) -> T,
{
    let (ax, ay) = (a[0], a[1]);
    f(ax, ay)
}

#[inline]
pub fn fold3<T, F>(a: Vector3<T>, f: F) -> T
where
    T: Copy,
    F: Fn(T, T) -> T,
{
    let (ax, ay, az) = (a[0], a[1], a[2]);
    f(f(ax, ay), az)
}

#[inline]
pub fn fold4<T, F>(a: Vector4<T>, f: F) -> T
where
    T: Copy,
    F: Fn(T, T) -> T,
{
    let (ax, ay, az, aw) = (a[0], a[1], a[2], a[3]);
    f(f(f(ax, ay), az), aw)
}

#[inline]
pub fn add2<T>(a: Point2<T>, b: Vector2<T>) -> Point2<T>
where
    T: Copy + Add<T, Output = T>,
{
    zip_with2(a, b, Add::add)
}

#[inline]
pub fn add3<T>(a: Point3<T>, b: Vector3<T>) -> Point3<T>
where
    T: Copy + Add<T, Output = T>,
{
    zip_with3(a, b, Add::add)
}

#[inline]
pub fn add4<T>(a: Point4<T>, b: Vector4<T>) -> Point4<T>
where
    T: Copy + Add<T, Output = T>,
{
    zip_with4(a, b, Add::add)
}

#[inline]
pub fn sub2<T>(a: Point2<T>, b: Point2<T>) -> Vector2<T>
where
    T: Copy + Sub<T, Output = T>,
{
    zip_with2(a, b, Sub::sub)
}

#[inline]
pub fn sub3<T>(a: Point3<T>, b: Point3<T>) -> Vector3<T>
where
    T: Copy + Sub<T, Output = T>,
{
    zip_with3(a, b, Sub::sub)
}

#[inline]
pub fn sub4<T>(a: Point4<T>, b: Point4<T>) -> Vector4<T>
where
    T: Copy + Sub<T, Output = T>,
{
    zip_with4(a, b, Sub::sub)
}

#[inline]
pub fn mul2<T>(a: Vector2<T>, b: T) -> Vector2<T>
where
    T: Copy + Mul<T, Output = T>,
{
    zip_with2(a, const2(b), Mul::mul)
}

#[inline]
pub fn mul3<T>(a: Vector3<T>, b: T) -> Vector3<T>
where
    T: Copy + Mul<T, Output = T>,
{
    zip_with3(a, const3(b), Mul::mul)
}

#[inline]
pub fn mul4<T>(a: Vector4<T>, b: T) -> Vector4<T>
where
    T: Copy + Mul<T, Output = T>,
{
    zip_with4(a, const4(b), Mul::mul)
}

#[inline]
pub fn dot2(a: Vector2<f64>, b: Vector2<f64>) -> f64 {
    fold2(zip_with2(a, b, Mul::mul), Add::add)
}

#[inline]
pub fn dot3(a: Vector3<f64>, b: Vector3<f64>) -> f64 {
    fold3(zip_with3(a, b, Mul::mul), Add::add)
}

#[inline]
pub fn dot4(a: Vector4<f64>, b: Vector4<f64>) -> f64 {
    fold4(zip_with4(a, b, Mul::mul), Add::add)
}

#[inline]
pub fn const2<T: Copy>(x: T) -> Vector2<T> {
    [x, x]
}

#[inline]
pub fn const3<T: Copy>(x: T) -> Vector3<T> {
    [x, x, x]
}

#[inline]
pub fn const4<T: Copy>(x: T) -> Vector4<T> {
    [x, x, x, x]
}

#[inline]
pub fn one2<T: Copy + From<i8>>() -> Vector2<T> {
    cast2(const2(1))
}

#[inline]
pub fn one3<T: Copy + From<i8>>() -> Vector3<T> {
    cast3(const3(1))
}

#[inline]
pub fn one4<T: Copy + From<i8>>() -> Vector4<T> {
    cast4(const4(1))
}

#[inline]
pub fn cast2<T, U>(x: Point2<T>) -> Point2<U>
where
    T: Copy,
    U: Copy + From<T>,
{
    map2(x, cast)
}

#[inline]
pub fn cast3<T, U>(x: Point3<T>) -> Point3<U>
where
    T: Copy,
    U: Copy + From<T>,
{
    map3(x, cast)
}

#[inline]
pub fn cast4<T, U>(x: Point4<T>) -> Point4<U>
where
    T: Copy,
    U: Copy + From<T>,
{
    map4(x, cast)
}

// f64 doesn't implement From<isize>
#[inline]
pub fn to_f642(x: Point2<isize>) -> Point2<f64> {
    [x[0] as f64, x[1] as f64]
}

#[inline]
pub fn to_f643(x: Point3<isize>) -> Point3<f64> {
    [x[0] as f64, x[1] as f64, x[2] as f64]
}

#[inline]
pub fn to_f644(x: Point4<isize>) -> Point4<f64> {
    [x[0] as f64, x[1] as f64, x[2] as f64, x[3] as f64]
}

// isize doesn't implement From<f64>
#[inline]
pub fn to_isize2(x: Point2<f64>) -> Point2<isize> {
    [x[0] as isize, x[1] as isize]
}

#[cfg(not(target_os = "emscripten"))]
#[inline]
pub fn scale_shift(value: f64, n: f64) -> f64 {
    value.abs().mul_add(n, -1.0_f64)
}

#[cfg(target_os = "emscripten")]
#[inline]
pub fn scale_shift(value: f64, n: f64) -> f64 {
    (value.abs() * n) + -1.0_f64
}

#[inline]
pub fn to_isize3(x: Point3<f64>) -> Point3<isize> {
    [x[0] as isize, x[1] as isize, x[2] as isize]
}

#[inline]
pub fn to_isize4(x: Point4<f64>) -> Point4<isize> {
    [x[0] as isize, x[1] as isize, x[2] as isize, x[3] as isize]
}

pub mod interp {
    /// Performs linear interploation between two values.
    #[cfg(not(target_os = "emscripten"))]
    #[inline]
    pub fn linear(a: f64, b: f64, x: f64) -> f64 {
        x.mul_add(b - a, a)
    }

    /// Performs linear interploation between two values.
    #[cfg(target_os = "emscripten")]
    #[inline]
    pub fn linear(a: f64, b: f64, x: f64) -> f64 {
        (x * (b - a)) + a
    }

    /// Performs cubic interpolation between two values bound between two other
    /// values.
    ///
    /// - n0 - The value before the first value.
    /// - n1 - The first value.
    /// - n2 - The second value.
    /// - n3 - The value after the second value.
    /// - x - The alpha value.
    ///
    /// The alpha value should range from 0.0 to 1.0. If the alpha value is
    /// 0.0, this function returns _n1_. If the alpha value is 1.0, this
    /// function returns _n2_.
    #[inline]
    pub fn cubic(n0: f64, n1: f64, n2: f64, n3: f64, x: f64) -> f64 {
        let p = (n3 - n2) - (n0 - n1);
        let q = (n0 - n1) - p;
        let r = n2 - n0;
        let s = n1;
        p * x * x * x + q * x * x + r * x + s
    }

    /// Maps a value onto a cubic S-curve.
    #[inline]
    pub fn s_curve3(x: f64) -> f64 {
        x * x * (3.0 - (x * 2.0))
    }

    /// Maps a value onto a quintic S-curve.
    #[inline]
    pub fn s_curve5(x: f64) -> f64 {
        x * x * x * (x * (x * 6.0 - 15.0) + 10.0)
    }
}
<|endoftext|>


<commit_before>use num::BigUint;
use num::traits::{Zero, One, FromPrimitive};
use digit_slice::{DigitSlice, FromDigits};
use {Shape, Noun, NockError, NockResult};

/// Evaluate the nock `*[subject formula]`
pub fn nock_on(mut subject: Noun, mut formula: Noun) -> NockResult {
    loop {
        if let Shape::Cell(ops, tail) = formula.clone().get() {
            match ops.as_u32() {
                // Axis
                Some(0) => {
                    match tail.get() {
                        Shape::Atom(ref x) => return axis(x, &subject),
                        _ => return Err(NockError),
                    }
                }

                // Just
                Some(1) => return Ok(tail.clone()),

                // Fire
                Some(2) => {
                    match tail.get() {
                        Shape::Cell(ref b, ref c) => {
                            let p = try!(nock_on(subject.clone(),
                                                 (*b).clone()));
                            let q = try!(nock_on(subject, (*c).clone()));
                            subject = p;
                            formula = q;
                            continue;
                        }
                        _ => return Err(NockError),
                    }
                }

                // Depth
                Some(3) => {
                    let p = try!(nock_on(subject.clone(), (*tail).clone()));
                    return match p.get() {
                        Shape::Cell(_, _) => Ok(Noun::from(0u32)),
                        _ => Ok(Noun::from(1u32)),
                    };
                }

                // Bump
                Some(4) => {
                    let p = try!(nock_on(subject.clone(), (*tail).clone()));
                    return match p.get() {
                        Shape::Atom(ref x) => {
                            // TODO: Non-bignum optimization
                            Ok(Noun::from(BigUint::from_digits(x).unwrap() +
                                          BigUint::one()))
                        }
                        _ => Err(NockError),
                    };
                }

                // Same
                Some(5) => {
                    let p = try!(nock_on(subject.clone(), (*tail).clone()));
                    return match p.get() {
                        Shape::Cell(ref a, ref b) => {
                            if a == b {
                                // Yes.
                                return Ok(Noun::from(0u32));
                            } else {
                                // No.
                                return Ok(Noun::from(1u32));
                            }
                        }
                        _ => return Err(NockError),
                    };
                }

                // If
                Some(6) => {
                    if let Some((b, c, d)) = tail.get_122() {
                        let p = try!(nock_on(subject.clone(), (*b).clone()));
                        match p.get() {
                            Shape::Atom(ref x) => {
                                if x == &0u32.as_digits() {
                                    formula = (*c).clone();
                                } else if x == &1u32.as_digits() {
                                    formula = (*d).clone();
                                } else {
                                    return Err(NockError);
                                }
                            }
                            _ => return Err(NockError),
                        }
                        continue;
                    } else {
                        return Err(NockError);
                    }
                }

                // Compose
                Some(7) => {
                    match tail.get() {
                        Shape::Cell(ref b, ref c) => {
                            let p = try!(nock_on(subject.clone(),
                                                 (*b).clone()));
                            subject = p;
                            formula = (*c).clone();
                            continue;
                        }
                        _ => return Err(NockError),
                    }
                }

                // Push
                Some(8) => {
                    match tail.get() {
                        Shape::Cell(ref b, ref c) => {
                            let p = try!(nock_on(subject.clone(),
                                                 (*b).clone()));
                            subject = Noun::cell(p, subject);
                            formula = (*c).clone();
                            continue;
                        }
                        _ => return Err(NockError),
                    }
                }

                // Call
                Some(9) => {
                    match tail.get() {
                        Shape::Cell(ref b, ref c) => {
                            subject = try!(nock_on(subject.clone(),
                                                   (*c).clone()));
                            formula = try!(nock_on(subject.clone(),
                                             Noun::cell(Noun::from(0u32),
                                                        (*b).clone())));
                            continue;
                        }
                        _ => return Err(NockError),
                    }
                }

                // Hint
                Some(10) => {
                    match tail.get() {
                        Shape::Cell(ref hint, ref c) => {
                            // Throw away hint.

                            // TODO: Check if hint is a cell and fail if it would
                            // crash.
                            formula = (*c).clone();
                            continue;
                        }
                        _ => return Err(NockError),
                    }
                }

                // Unhandled opcode
                Some(_) => {
                    return Err(NockError);
                }

                None => {
                    if let Shape::Cell(_, _) = ops.get() {
                        // Autocons
                        let a = try!(nock_on(subject.clone(), ops.clone()));
                        let b = try!(nock_on(subject, tail.clone()));
                        return Ok(Noun::cell(a, b));
                    } else {
                        return Err(NockError);
                    }
                }
            }
        } else {
            return Err(NockError);
        }
    }
}

fn axis(atom: &[u8], subject: &Noun) -> NockResult {
    // TODO: Optimize for small atoms.
    fn fas(x: BigUint, n: &Noun) -> NockResult {
        let two = BigUint::from_u32(2).unwrap();
        let three = BigUint::from_u32(3).unwrap();
        if x == BigUint::zero() {
            return Err(NockError);
        }
        if x == BigUint::one() {
            return Ok(n.clone());
        }
        if let Shape::Cell(ref a, ref b) = n.get() {
            if x == two {
                return Ok((*a).clone());
            } else if x == three {
                return Ok((*b).clone());
            } else {
                let half = x.clone() >> 1;
                let p = try!(fas(half, n));

                if x % two.clone() == BigUint::zero() {
                    fas(two, &p)
                } else {
                    fas(three, &p)
                }
            }
        } else {
            return Err(NockError);
        }
    }

    fas(BigUint::from_digits(atom).unwrap(), subject)
}
<commit_msg>Axis fn takes noun axis<commit_after>use num::BigUint;
use num::traits::{Zero, One, FromPrimitive};
use digit_slice::{DigitSlice, FromDigits};
use {Shape, Noun, NockError, NockResult};

/// Evaluate the nock `*[subject formula]`
pub fn nock_on(mut subject: Noun, mut formula: Noun) -> NockResult {
    loop {
        if let Shape::Cell(ops, tail) = formula.clone().get() {
            match ops.as_u32() {
                // Axis
                Some(0) => return axis(&tail, &subject),

                // Just
                Some(1) => return Ok(tail.clone()),

                // Fire
                Some(2) => {
                    match tail.get() {
                        Shape::Cell(ref b, ref c) => {
                            let p = try!(nock_on(subject.clone(),
                                                 (*b).clone()));
                            let q = try!(nock_on(subject, (*c).clone()));
                            subject = p;
                            formula = q;
                            continue;
                        }
                        _ => return Err(NockError),
                    }
                }

                // Depth
                Some(3) => {
                    let p = try!(nock_on(subject.clone(), (*tail).clone()));
                    return match p.get() {
                        Shape::Cell(_, _) => Ok(Noun::from(0u32)),
                        _ => Ok(Noun::from(1u32)),
                    };
                }

                // Bump
                Some(4) => {
                    let p = try!(nock_on(subject.clone(), (*tail).clone()));
                    return match p.get() {
                        Shape::Atom(ref x) => {
                            // TODO: Non-bignum optimization
                            Ok(Noun::from(BigUint::from_digits(x).unwrap() +
                                          BigUint::one()))
                        }
                        _ => Err(NockError),
                    };
                }

                // Same
                Some(5) => {
                    let p = try!(nock_on(subject.clone(), (*tail).clone()));
                    return match p.get() {
                        Shape::Cell(ref a, ref b) => {
                            if a == b {
                                // Yes.
                                return Ok(Noun::from(0u32));
                            } else {
                                // No.
                                return Ok(Noun::from(1u32));
                            }
                        }
                        _ => return Err(NockError),
                    };
                }

                // If
                Some(6) => {
                    if let Some((b, c, d)) = tail.get_122() {
                        let p = try!(nock_on(subject.clone(), (*b).clone()));
                        match p.get() {
                            Shape::Atom(ref x) => {
                                if x == &0u32.as_digits() {
                                    formula = (*c).clone();
                                } else if x == &1u32.as_digits() {
                                    formula = (*d).clone();
                                } else {
                                    return Err(NockError);
                                }
                            }
                            _ => return Err(NockError),
                        }
                        continue;
                    } else {
                        return Err(NockError);
                    }
                }

                // Compose
                Some(7) => {
                    match tail.get() {
                        Shape::Cell(ref b, ref c) => {
                            let p = try!(nock_on(subject.clone(),
                                                 (*b).clone()));
                            subject = p;
                            formula = (*c).clone();
                            continue;
                        }
                        _ => return Err(NockError),
                    }
                }

                // Push
                Some(8) => {
                    match tail.get() {
                        Shape::Cell(ref b, ref c) => {
                            let p = try!(nock_on(subject.clone(),
                                                 (*b).clone()));
                            subject = Noun::cell(p, subject);
                            formula = (*c).clone();
                            continue;
                        }
                        _ => return Err(NockError),
                    }
                }

                // Call
                Some(9) => {
                    match tail.get() {
                        Shape::Cell(ref b, ref c) => {
                            subject = try!(nock_on(subject.clone(),
                                                   (*c).clone()));
                            formula = try!(nock_on(subject.clone(),
                                             Noun::cell(Noun::from(0u32),
                                                        (*b).clone())));
                            continue;
                        }
                        _ => return Err(NockError),
                    }
                }

                // Hint
                Some(10) => {
                    match tail.get() {
                        Shape::Cell(ref hint, ref c) => {
                            // Throw away hint.

                            // TODO: Check if hint is a cell and fail if it would
                            // crash.
                            formula = (*c).clone();
                            continue;
                        }
                        _ => return Err(NockError),
                    }
                }

                // Unhandled opcode
                Some(_) => {
                    return Err(NockError);
                }

                None => {
                    if let Shape::Cell(_, _) = ops.get() {
                        // Autocons
                        let a = try!(nock_on(subject.clone(), ops.clone()));
                        let b = try!(nock_on(subject, tail.clone()));
                        return Ok(Noun::cell(a, b));
                    } else {
                        return Err(NockError);
                    }
                }
            }
        } else {
            return Err(NockError);
        }
    }
}

fn axis(a: &Noun, subject: &Noun) -> NockResult {
    // TODO: Optimize for small atoms.
    fn fas(x: BigUint, n: &Noun) -> NockResult {
        let two = BigUint::from_u32(2).unwrap();
        let three = BigUint::from_u32(3).unwrap();
        if x == BigUint::zero() {
            return Err(NockError);
        }
        if x == BigUint::one() {
            return Ok(n.clone());
        }
        if let Shape::Cell(ref a, ref b) = n.get() {
            if x == two {
                return Ok((*a).clone());
            } else if x == three {
                return Ok((*b).clone());
            } else {
                let half = x.clone() >> 1;
                let p = try!(fas(half, n));

                if x % two.clone() == BigUint::zero() {
                    fas(two, &p)
                } else {
                    fas(three, &p)
                }
            }
        } else {
            return Err(NockError);
        }
    }

    match a.get() {
        Shape::Atom(ref x) => fas(BigUint::from_digits(x).unwrap(), subject),
        _ => Err(NockError)
    }
}
<|endoftext|>


<commit_before>/* Sample insertion sort program in Rust.
   Tested to compile with rust-0.6.
 */
extern mod extra;
extern mod benchmark;
use std::vec;
use benchmark::Benchmark;

fn insertion_sort<T:Ord+Copy>(arr: ~[T]) -> ~[T] {
    let mut index = 0;
    let length = arr.len();
    let mut result = copy arr;

    while index < length {
        let valueToInsert = result[index];
        let mut holePos = index;

        while holePos > 0 && valueToInsert < result[holePos - 1] {
            vec::swap(result, holePos, holePos - 1);
            holePos -= 1;
        }
        index += 1;
    }

    return result
}

fn main() {
    let mut bench = Benchmark::new();
    bench.run(insertion_sort);
}

<commit_msg>Fix failing build by using explicit copy.  Should probably be re-worked to use moves instead<commit_after>/* Sample insertion sort program in Rust.
   Tested to compile with rust-0.6.
 */
extern mod extra;
extern mod benchmark;
use std::vec;
use benchmark::Benchmark;

fn insertion_sort<T:Ord+Copy>(arr: ~[T]) -> ~[T] {
    let mut index = 0;
    let length = arr.len();
    let mut result = copy arr;

    while index < length {
        let valueToInsert = copy result[index];
        let mut holePos = index;

        while holePos > 0 && valueToInsert < result[holePos - 1] {
            vec::swap(result, holePos, holePos - 1);
            holePos -= 1;
        }
        index += 1;
    }

    return result
}

fn main() {
    let mut bench = Benchmark::new();
    bench.run(insertion_sort);
}

<|endoftext|>


<commit_before>use std::ffi::CString;
use std::fmt;
use std::mem;
use std::ptr;
use std::slice;
use std::str::{self, FromStr};

use libc::{c_char, c_int, c_void};
use ffi;

use error::{self, Error, Result};
use mpi::Integer;
use mpi::integer::Format as IntegerFormat;

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Format {
    Default   = ffi::GCRYSEXP_FMT_DEFAULT as isize,
    Canonical = ffi::GCRYSEXP_FMT_CANON as isize,
    Base64    = ffi::GCRYSEXP_FMT_BASE64 as isize,
    Advanced  = ffi::GCRYSEXP_FMT_ADVANCED as isize,
}

pub struct SExpression(ffi::gcry_sexp_t);

impl_wrapper!(SExpression: ffi::gcry_sexp_t);

impl Drop for SExpression {
    fn drop(&mut self) {
        unsafe {
            ffi::gcry_sexp_release(self.0);
        }
    }
}

impl SExpression {
    pub fn from_bytes<B: AsRef<[u8]>>(bytes: B) -> Result<SExpression> {
        let bytes = bytes.as_ref();
        let _ = ::get_token();
        unsafe {
            let mut result: ffi::gcry_sexp_t = ptr::null_mut();
            return_err!(ffi::gcry_sexp_sscan(&mut result,
                                             ptr::null_mut(),
                                             bytes.as_ptr() as *const _,
                                             bytes.len()));
            Ok(SExpression::from_raw(result))
        }
    }

    pub fn to_bytes(&self, format: Format) -> Vec<u8> {
        let mut buffer = vec![0; self.len_encoded(format)];
        self.encode(format, &mut buffer);
        buffer.pop();
        buffer
    }

    pub fn len_encoded(&self, format: Format) -> usize {
        unsafe { ffi::gcry_sexp_sprint(self.0, format as c_int, ptr::null_mut(), 0) }
    }

    pub fn encode(&self, format: Format, buf: &mut [u8]) -> Option<usize> {
        unsafe {
            match ffi::gcry_sexp_sprint(self.0,
                                        format as c_int,
                                        buf.as_mut_ptr() as *mut _,
                                        buf.len()) {
                0 => None,
                x => Some(x),
            }
        }
    }

    pub fn elements(&self) -> Elements {
        unsafe {
            Elements {
                sexp: self,
                first: 0,
                last: ffi::gcry_sexp_length(self.0),
            }
        }
    }

    pub fn head(&self) -> Option<SExpression> {
        unsafe { ffi::gcry_sexp_car(self.0).as_mut().map(|x| SExpression::from_raw(x)) }
    }

    pub fn tail(&self) -> Option<SExpression> {
        unsafe { ffi::gcry_sexp_cdr(self.0).as_mut().map(|x| SExpression::from_raw(x)) }
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn len(&self) -> usize {
        unsafe { ffi::gcry_sexp_length(self.0) as usize }
    }

    pub fn find_token<B: AsRef<[u8]>>(&self, token: B) -> Option<SExpression> {
        let token = token.as_ref();
        unsafe {
            ffi::gcry_sexp_find_token(self.0, token.as_ptr() as *const _, token.len())
                .as_mut()
                .map(|x| SExpression::from_raw(x))
        }
    }

    pub fn get(&self, idx: u32) -> Option<SExpression> {
        unsafe {
            ffi::gcry_sexp_nth(self.0, idx as c_int).as_mut().map(|x| SExpression::from_raw(x))
        }
    }

    pub fn get_bytes(&self, idx: u32) -> Option<&[u8]> {
        unsafe {
            let mut len = 0;
            ffi::gcry_sexp_nth_data(self.0, idx as c_int, &mut len)
                .as_ref()
                .map(|x| slice::from_raw_parts(x as *const _ as *const _, len))
        }
    }

    pub fn get_str(&self, idx: u32) -> Option<&str> {
        self.get_bytes(idx).and_then(|b| str::from_utf8(b).ok())
    }

    pub fn get_integer(&self, idx: u32, fmt: IntegerFormat) -> Option<Integer> {
        unsafe {
            ffi::gcry_sexp_nth_mpi(self.0, idx as c_int, fmt as c_int)
                .as_mut()
                .map(|x| Integer::from_raw(x))
        }
    }
}

impl FromStr for SExpression {
    type Err = Error;

    fn from_str(s: &str) -> Result<SExpression> {
        SExpression::from_bytes(s)
    }
}

impl fmt::Display for SExpression {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some((_, result)) = self.to_bytes(Format::Advanced).split_last() {
            try!(f.write_str(&String::from_utf8_lossy(result)));
        }
        Ok(())
    }
}

impl<'a> IntoIterator for &'a SExpression {
    type Item = SExpression;
    type IntoIter = Elements<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.elements()
    }
}

pub struct Elements<'a> {
    sexp: &'a SExpression,
    first: c_int,
    last: c_int,
}

impl<'a> Iterator for Elements<'a> {
    type Item = SExpression;

    fn next(&mut self) -> Option<Self::Item> {
        if self.first < self.last {
            let elem = unsafe {
                let raw = ffi::gcry_sexp_nth(self.sexp.as_raw(), self.first);
                SExpression::from_raw(raw)
            };
            self.first += 1;
            Some(elem)
        } else {
            None
        }
    }

    fn last(mut self) -> Option<Self::Item> {
        self.next_back()
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        self.first = if (n as u64) < (self.last as u64) {
            self.first + (n as c_int)
        } else {
            self.last
        };
        self.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let size = (self.last - self.first) as usize;
        (size, Some(size))
    }
}
impl<'a> DoubleEndedIterator for Elements<'a> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.first < self.last {
            self.last -= 1;
            unsafe {
                let raw = ffi::gcry_sexp_nth(self.sexp.as_raw(), self.last);
                Some(SExpression::from_raw(raw))
            }
        } else {
            None
        }
    }
}
impl<'a> ExactSizeIterator for Elements<'a> {}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
enum ParameterKind {
    Integer,
    Bytes,
    Mpi,
    SExpression,
}

enum Parameter {
    Integer(c_int),
    Bytes(c_int, *const c_char),
    Mpi(ffi::gcry_mpi_t),
    SExpression(ffi::gcry_sexp_t),
}

#[derive(Debug, Clone)]
pub struct Template {
    format: CString,
    params: Vec<ParameterKind>,
}

impl Template {
    pub fn new(format: &str) -> Result<Template> {
        let mut new_format = Vec::with_capacity(format.len());
        let mut params = Vec::new();
        let mut it = format.bytes();
        loop {
            match it.next() {
                Some(b'%') => {
                    new_format.push(b'%');
                    let kind = match it.next() {
                        Some(x) if (x == b'd') || (x == b'u') => {
                            new_format.push(x);
                            ParameterKind::Integer
                        }
                        Some(b'b') | Some(b's') => {
                            new_format.push(b'b');
                            ParameterKind::Bytes
                        }
                        Some(x) if (x == b'm') || (x == b'M') => {
                            new_format.push(x);
                            ParameterKind::Mpi
                        }
                        Some(b'S') => {
                            new_format.push(b'S');
                            ParameterKind::SExpression
                        }
                        _ => return Err(Error::from_code(error::GPG_ERR_INV_ARG)),
                    };
                    params.push(kind);
                }
                Some(b'\0') => return Err(Error::from_code(error::GPG_ERR_INV_ARG)),
                Some(x) => new_format.push(x),
                None => break,
            }
        }
        unsafe {
            Ok(Template {
                format: CString::from_vec_unchecked(new_format),
                params: params,
            })
        }
    }
}

pub struct Builder<'a> {
    template: &'a Template,
    params: Vec<Parameter>,
}

impl<'a> Builder<'a> {
    pub fn from(template: &Template) -> Builder {
        Builder {
            template: template,
            params: Vec::new(),
        }
    }

    pub fn add_int(&mut self, n: i32) -> &mut Self {
        assert_eq!(self.template.params.get(self.params.len()),
                   Some(&ParameterKind::Integer));
        self.params.push(Parameter::Integer(n as c_int));
        self
    }

    pub fn add_bytes<'s, 'b: 's, B: ?Sized>(&'s mut self, bytes: &'b B) -> &mut Self
    where B: AsRef<[u8]> {
        assert_eq!(self.template.params.get(self.params.len()),
                   Some(&ParameterKind::Bytes));
        let bytes = bytes.as_ref();
        self.params.push(Parameter::Bytes(bytes.len() as c_int, bytes.as_ptr() as *const _));
        self
    }

    pub fn add_str<'s, 'b: 's, S: ?Sized>(&'s mut self, string: &'b S) -> &mut Self
    where S: AsRef<str> {
        self.add_bytes(string.as_ref())
    }

    pub fn add_mpi<'s, 'b: 's>(&'s mut self, n: &'b Integer) -> &mut Self {
        assert_eq!(self.template.params.get(self.params.len()),
                   Some(&ParameterKind::Mpi));
        self.params.push(Parameter::Mpi(n.as_raw()));
        self
    }

    pub fn add_sexp<'s, 'b: 's>(&'s mut self, s: &'b SExpression) -> &mut Self {
        assert_eq!(self.template.params.get(self.params.len()),
                   Some(&ParameterKind::SExpression));
        self.params.push(Parameter::SExpression(s.as_raw()));
        self
    }

    pub fn build(self) -> Result<SExpression> {
        if self.params.len() != self.template.params.len() {
            return Err(Error::from_code(error::GPG_ERR_INV_STATE));
        }
        let _ = ::get_token();
        unsafe {
            let mut args = Vec::<*mut c_void>::with_capacity(self.params.len());
            for param in &self.params {
                match *param {
                    Parameter::Integer(ref x) => args.push(mem::transmute(x)),
                    Parameter::Bytes(ref len, ref data) => {
                        args.push(mem::transmute(len));
                        args.push(mem::transmute(data));
                    }
                    Parameter::Mpi(ref x) => args.push(mem::transmute(x)),
                    Parameter::SExpression(ref s) => args.push(mem::transmute(s)),
                }
            }
            args.push(ptr::null_mut());

            let mut result: ffi::gcry_sexp_t = ptr::null_mut();
            return_err!(ffi::gcry_sexp_build_array(&mut result,
                                                   ptr::null_mut(),
                                                   self.template.format.as_ptr(),
                                                   args.as_mut_ptr()));
            Ok(SExpression::from_raw(result))
        }
    }
}

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

    #[test]
    fn test_build() {
        let template = Template::new("(private-key(ecc(curve %s)(flags eddsa)(q %d)(d %b)))")
            .unwrap();
        let mut builder = Builder::from(&template);
        builder.add_str("ed25519").add_int(1234).add_bytes("2324");
        builder.build().unwrap();
    }
}
<commit_msg>Remove SExpression builder<commit_after>use std::fmt;
use std::ptr;
use std::slice;
use std::str::{self, FromStr};

use libc::c_int;
use ffi;

use error::{Error, Result};
use mpi::Integer;
use mpi::integer::Format as IntegerFormat;

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Format {
    Default   = ffi::GCRYSEXP_FMT_DEFAULT as isize,
    Canonical = ffi::GCRYSEXP_FMT_CANON as isize,
    Base64    = ffi::GCRYSEXP_FMT_BASE64 as isize,
    Advanced  = ffi::GCRYSEXP_FMT_ADVANCED as isize,
}

pub struct SExpression(ffi::gcry_sexp_t);

impl_wrapper!(SExpression: ffi::gcry_sexp_t);

impl Drop for SExpression {
    fn drop(&mut self) {
        unsafe {
            ffi::gcry_sexp_release(self.0);
        }
    }
}

impl SExpression {
    pub fn from_bytes<B: AsRef<[u8]>>(bytes: B) -> Result<SExpression> {
        let bytes = bytes.as_ref();
        let _ = ::get_token();
        unsafe {
            let mut result: ffi::gcry_sexp_t = ptr::null_mut();
            return_err!(ffi::gcry_sexp_sscan(&mut result,
                                             ptr::null_mut(),
                                             bytes.as_ptr() as *const _,
                                             bytes.len()));
            Ok(SExpression::from_raw(result))
        }
    }

    pub fn to_bytes(&self, format: Format) -> Vec<u8> {
        let mut buffer = vec![0; self.len_encoded(format)];
        self.encode(format, &mut buffer);
        buffer.pop();
        buffer
    }

    pub fn len_encoded(&self, format: Format) -> usize {
        unsafe { ffi::gcry_sexp_sprint(self.0, format as c_int, ptr::null_mut(), 0) }
    }

    pub fn encode(&self, format: Format, buf: &mut [u8]) -> Option<usize> {
        unsafe {
            match ffi::gcry_sexp_sprint(self.0,
                                        format as c_int,
                                        buf.as_mut_ptr() as *mut _,
                                        buf.len()) {
                0 => None,
                x => Some(x),
            }
        }
    }

    pub fn elements(&self) -> Elements {
        unsafe {
            Elements {
                sexp: self,
                first: 0,
                last: ffi::gcry_sexp_length(self.0),
            }
        }
    }

    pub fn head(&self) -> Option<SExpression> {
        unsafe { ffi::gcry_sexp_car(self.0).as_mut().map(|x| SExpression::from_raw(x)) }
    }

    pub fn tail(&self) -> Option<SExpression> {
        unsafe { ffi::gcry_sexp_cdr(self.0).as_mut().map(|x| SExpression::from_raw(x)) }
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn len(&self) -> usize {
        unsafe { ffi::gcry_sexp_length(self.0) as usize }
    }

    pub fn find_token<B: AsRef<[u8]>>(&self, token: B) -> Option<SExpression> {
        let token = token.as_ref();
        unsafe {
            ffi::gcry_sexp_find_token(self.0, token.as_ptr() as *const _, token.len())
                .as_mut()
                .map(|x| SExpression::from_raw(x))
        }
    }

    pub fn get(&self, idx: u32) -> Option<SExpression> {
        unsafe {
            ffi::gcry_sexp_nth(self.0, idx as c_int).as_mut().map(|x| SExpression::from_raw(x))
        }
    }

    pub fn get_bytes(&self, idx: u32) -> Option<&[u8]> {
        unsafe {
            let mut len = 0;
            ffi::gcry_sexp_nth_data(self.0, idx as c_int, &mut len)
                .as_ref()
                .map(|x| slice::from_raw_parts(x as *const _ as *const _, len))
        }
    }

    pub fn get_str(&self, idx: u32) -> Option<&str> {
        self.get_bytes(idx).and_then(|b| str::from_utf8(b).ok())
    }

    pub fn get_integer(&self, idx: u32, fmt: IntegerFormat) -> Option<Integer> {
        unsafe {
            ffi::gcry_sexp_nth_mpi(self.0, idx as c_int, fmt as c_int)
                .as_mut()
                .map(|x| Integer::from_raw(x))
        }
    }
}

impl FromStr for SExpression {
    type Err = Error;

    fn from_str(s: &str) -> Result<SExpression> {
        SExpression::from_bytes(s)
    }
}

impl fmt::Display for SExpression {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some((_, result)) = self.to_bytes(Format::Advanced).split_last() {
            try!(f.write_str(&String::from_utf8_lossy(result)));
        }
        Ok(())
    }
}

impl<'a> IntoIterator for &'a SExpression {
    type Item = SExpression;
    type IntoIter = Elements<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.elements()
    }
}

pub struct Elements<'a> {
    sexp: &'a SExpression,
    first: c_int,
    last: c_int,
}

impl<'a> Iterator for Elements<'a> {
    type Item = SExpression;

    fn next(&mut self) -> Option<Self::Item> {
        if self.first < self.last {
            let elem = unsafe {
                let raw = ffi::gcry_sexp_nth(self.sexp.as_raw(), self.first);
                SExpression::from_raw(raw)
            };
            self.first += 1;
            Some(elem)
        } else {
            None
        }
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        self.first = if (n as u64) < (self.last as u64) {
            self.first + (n as c_int)
        } else {
            self.last
        };
        self.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let size = (self.last - self.first) as usize;
        (size, Some(size))
    }
}
impl<'a> DoubleEndedIterator for Elements<'a> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.first < self.last {
            self.last -= 1;
            unsafe {
                let raw = ffi::gcry_sexp_nth(self.sexp.as_raw(), self.last);
                Some(SExpression::from_raw(raw))
            }
        } else {
            None
        }
    }
}
impl<'a> ExactSizeIterator for Elements<'a> {}
<|endoftext|>


<commit_before>use core::ops::Neg;
use core::num::Wrapping;

use Num;
use float::FloatCore;

/// Useful functions for signed numbers (i.e. numbers that can be negative).
pub trait Signed: Sized + Num + Neg<Output = Self> {
    /// Computes the absolute value.
    ///
    /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`.
    ///
    /// For signed integers, `::MIN` will be returned if the number is `::MIN`.
    fn abs(&self) -> Self;

    /// The positive difference of two numbers.
    ///
    /// Returns `zero` if the number is less than or equal to `other`, otherwise the difference
    /// between `self` and `other` is returned.
    fn abs_sub(&self, other: &Self) -> Self;

    /// Returns the sign of the number.
    ///
    /// For `f32` and `f64`:
    ///
    /// * `1.0` if the number is positive, `+0.0` or `INFINITY`
    /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
    /// * `NaN` if the number is `NaN`
    ///
    /// For signed integers:
    ///
    /// * `0` if the number is zero
    /// * `1` if the number is positive
    /// * `-1` if the number is negative
    fn signum(&self) -> Self;

    /// Returns true if the number is positive and false if the number is zero or negative.
    fn is_positive(&self) -> bool;

    /// Returns true if the number is negative and false if the number is zero or positive.
    fn is_negative(&self) -> bool;
}

macro_rules! signed_impl {
    ($($t:ty)*) => ($(
        impl Signed for $t {
            #[inline]
            fn abs(&self) -> $t {
                if self.is_negative() { -*self } else { *self }
            }

            #[inline]
            fn abs_sub(&self, other: &$t) -> $t {
                if *self <= *other { 0 } else { *self - *other }
            }

            #[inline]
            fn signum(&self) -> $t {
                match *self {
                    n if n > 0 => 1,
                    0 => 0,
                    _ => -1,
                }
            }

            #[inline]
            fn is_positive(&self) -> bool { *self > 0 }

            #[inline]
            fn is_negative(&self) -> bool { *self < 0 }
        }
    )*)
}

signed_impl!(isize i8 i16 i32 i64);

#[cfg(feature = "i128")]
signed_impl!(i128);

impl<T: Signed> Signed for Wrapping<T> where Wrapping<T>: Num + Neg<Output=Wrapping<T>>
{
    #[inline]
    fn abs(&self) -> Self {
        Wrapping(self.0.abs())
    }

    #[inline]
    fn abs_sub(&self, other: &Self) -> Self {
        Wrapping(self.0.abs_sub(&other.0))
    }

    #[inline]
    fn signum(&self) -> Self {
        Wrapping(self.0.signum())
    }

    #[inline]
    fn is_positive(&self) -> bool { self.0.is_positive() }

    #[inline]
    fn is_negative(&self) -> bool { self.0.is_negative() }
}

macro_rules! signed_float_impl {
    ($t:ty) => {
        impl Signed for $t {
            /// Computes the absolute value. Returns `NAN` if the number is `NAN`.
            #[inline]
            fn abs(&self) -> $t {
                FloatCore::abs(*self)
            }

            /// The positive difference of two numbers. Returns `0.0` if the number is
            /// less than or equal to `other`, otherwise the difference between`self`
            /// and `other` is returned.
            #[inline]
            fn abs_sub(&self, other: &$t) -> $t {
                if *self <= *other { 0. } else { *self - *other }
            }

            /// # Returns
            ///
            /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
            /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
            /// - `NAN` if the number is NaN
            #[inline]
            fn signum(&self) -> $t {
                FloatCore::signum(*self)
            }

            /// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
            #[inline]
            fn is_positive(&self) -> bool { FloatCore::is_sign_positive(*self) }

            /// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
            #[inline]
            fn is_negative(&self) -> bool { FloatCore::is_sign_negative(*self) }
        }
    }
}

signed_float_impl!(f32);
signed_float_impl!(f64);

/// Computes the absolute value.
///
/// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`
///
/// For signed integers, `::MIN` will be returned if the number is `::MIN`.
#[inline(always)]
pub fn abs<T: Signed>(value: T) -> T {
    value.abs()
}

/// The positive difference of two numbers.
///
/// Returns zero if `x` is less than or equal to `y`, otherwise the difference
/// between `x` and `y` is returned.
#[inline(always)]
pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
    x.abs_sub(&y)
}

/// Returns the sign of the number.
///
/// For `f32` and `f64`:
///
/// * `1.0` if the number is positive, `+0.0` or `INFINITY`
/// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
/// * `NaN` if the number is `NaN`
///
/// For signed integers:
///
/// * `0` if the number is zero
/// * `1` if the number is positive
/// * `-1` if the number is negative
#[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }

/// A trait for values which cannot be negative
pub trait Unsigned: Num {}

macro_rules! empty_trait_impl {
    ($name:ident for $($t:ty)*) => ($(
        impl $name for $t {}
    )*)
}

empty_trait_impl!(Unsigned for usize u8 u16 u32 u64);

impl<T: Unsigned> Unsigned for Wrapping<T> where Wrapping<T>: Num {}

#[test]
fn unsigned_wrapping_is_unsigned() {
    fn require_unsigned<T: Unsigned>(_: &T) {}
    require_unsigned(&Wrapping(42_u32));
}
/*
// Commenting this out since it doesn't compile on Rust 1.8,
// because on this version Wrapping doesn't implement Neg and therefore can't
// implement Signed.
#[test]
fn signed_wrapping_is_signed() {
    fn require_signed<T: Signed>(_: &T) {}
    require_signed(&Wrapping(-42));
}
*/
<commit_msg>Added impls of `Unsigned` for `i128` and `u128`<commit_after>use core::ops::Neg;
use core::num::Wrapping;

use Num;
use float::FloatCore;

/// Useful functions for signed numbers (i.e. numbers that can be negative).
pub trait Signed: Sized + Num + Neg<Output = Self> {
    /// Computes the absolute value.
    ///
    /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`.
    ///
    /// For signed integers, `::MIN` will be returned if the number is `::MIN`.
    fn abs(&self) -> Self;

    /// The positive difference of two numbers.
    ///
    /// Returns `zero` if the number is less than or equal to `other`, otherwise the difference
    /// between `self` and `other` is returned.
    fn abs_sub(&self, other: &Self) -> Self;

    /// Returns the sign of the number.
    ///
    /// For `f32` and `f64`:
    ///
    /// * `1.0` if the number is positive, `+0.0` or `INFINITY`
    /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
    /// * `NaN` if the number is `NaN`
    ///
    /// For signed integers:
    ///
    /// * `0` if the number is zero
    /// * `1` if the number is positive
    /// * `-1` if the number is negative
    fn signum(&self) -> Self;

    /// Returns true if the number is positive and false if the number is zero or negative.
    fn is_positive(&self) -> bool;

    /// Returns true if the number is negative and false if the number is zero or positive.
    fn is_negative(&self) -> bool;
}

macro_rules! signed_impl {
    ($($t:ty)*) => ($(
        impl Signed for $t {
            #[inline]
            fn abs(&self) -> $t {
                if self.is_negative() { -*self } else { *self }
            }

            #[inline]
            fn abs_sub(&self, other: &$t) -> $t {
                if *self <= *other { 0 } else { *self - *other }
            }

            #[inline]
            fn signum(&self) -> $t {
                match *self {
                    n if n > 0 => 1,
                    0 => 0,
                    _ => -1,
                }
            }

            #[inline]
            fn is_positive(&self) -> bool { *self > 0 }

            #[inline]
            fn is_negative(&self) -> bool { *self < 0 }
        }
    )*)
}

signed_impl!(isize i8 i16 i32 i64);

#[cfg(feature = "i128")]
signed_impl!(i128);

impl<T: Signed> Signed for Wrapping<T> where Wrapping<T>: Num + Neg<Output=Wrapping<T>>
{
    #[inline]
    fn abs(&self) -> Self {
        Wrapping(self.0.abs())
    }

    #[inline]
    fn abs_sub(&self, other: &Self) -> Self {
        Wrapping(self.0.abs_sub(&other.0))
    }

    #[inline]
    fn signum(&self) -> Self {
        Wrapping(self.0.signum())
    }

    #[inline]
    fn is_positive(&self) -> bool { self.0.is_positive() }

    #[inline]
    fn is_negative(&self) -> bool { self.0.is_negative() }
}

macro_rules! signed_float_impl {
    ($t:ty) => {
        impl Signed for $t {
            /// Computes the absolute value. Returns `NAN` if the number is `NAN`.
            #[inline]
            fn abs(&self) -> $t {
                FloatCore::abs(*self)
            }

            /// The positive difference of two numbers. Returns `0.0` if the number is
            /// less than or equal to `other`, otherwise the difference between`self`
            /// and `other` is returned.
            #[inline]
            fn abs_sub(&self, other: &$t) -> $t {
                if *self <= *other { 0. } else { *self - *other }
            }

            /// # Returns
            ///
            /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
            /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
            /// - `NAN` if the number is NaN
            #[inline]
            fn signum(&self) -> $t {
                FloatCore::signum(*self)
            }

            /// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
            #[inline]
            fn is_positive(&self) -> bool { FloatCore::is_sign_positive(*self) }

            /// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
            #[inline]
            fn is_negative(&self) -> bool { FloatCore::is_sign_negative(*self) }
        }
    }
}

signed_float_impl!(f32);
signed_float_impl!(f64);

/// Computes the absolute value.
///
/// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`
///
/// For signed integers, `::MIN` will be returned if the number is `::MIN`.
#[inline(always)]
pub fn abs<T: Signed>(value: T) -> T {
    value.abs()
}

/// The positive difference of two numbers.
///
/// Returns zero if `x` is less than or equal to `y`, otherwise the difference
/// between `x` and `y` is returned.
#[inline(always)]
pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
    x.abs_sub(&y)
}

/// Returns the sign of the number.
///
/// For `f32` and `f64`:
///
/// * `1.0` if the number is positive, `+0.0` or `INFINITY`
/// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
/// * `NaN` if the number is `NaN`
///
/// For signed integers:
///
/// * `0` if the number is zero
/// * `1` if the number is positive
/// * `-1` if the number is negative
#[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }

/// A trait for values which cannot be negative
pub trait Unsigned: Num {}

macro_rules! empty_trait_impl {
    ($name:ident for $($t:ty)*) => ($(
        impl $name for $t {}
    )*)
}

empty_trait_impl!(Unsigned for usize u8 u16 u32 u64);
#[cfg(feature = "i128")]
empty_trait_impl!(Unsigned for u128 i128);

impl<T: Unsigned> Unsigned for Wrapping<T> where Wrapping<T>: Num {}

#[test]
fn unsigned_wrapping_is_unsigned() {
    fn require_unsigned<T: Unsigned>(_: &T) {}
    require_unsigned(&Wrapping(42_u32));
}
/*
// Commenting this out since it doesn't compile on Rust 1.8,
// because on this version Wrapping doesn't implement Neg and therefore can't
// implement Signed.
#[test]
fn signed_wrapping_is_signed() {
    fn require_signed<T: Signed>(_: &T) {}
    require_signed(&Wrapping(-42));
}
*/
<|endoftext|>


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

// Contains helpers for:
//   exec_prompt
//   interfaces
//   formatting secrets
//
//   Consider: What else should be in here? Should
//   formatting secrets be in crypto? Should interfaces
//   have their own module?

use error::SsError;
use proxy::prompt::PromptInterfaceProxy;
use proxy::service::ServiceInterfaceProxy;
use session::Session;
use ss::SS_DBUS_NAME;
use ss_crypto::encrypt;
use proxy::SecretStruct;
use proxy::item::SecretStructInput;

use rand::{Rng, rngs::OsRng};
use std::sync::mpsc::channel;
use zvariant::ObjectPath;

// Helper enum for locking
pub(crate) enum LockAction {
    Lock,
    Unlock,
}

pub(crate) fn lock_or_unlock(
    conn: zbus::Connection,
    service_interface: &ServiceInterfaceProxy,
    object_path: &ObjectPath,
    lock_action: LockAction
    ) -> ::Result<()>
{
    let objects = vec![object_path];

    let lock_action_res = match lock_action {
        LockAction::Lock => service_interface.lock(objects)?,
        LockAction::Unlock => service_interface.unlock(objects)?,
    };

    if lock_action_res.object_paths.is_empty() {
        exec_prompt(conn.clone(), &lock_action_res.prompt)?;
    }
    Ok(())
}

pub(crate) fn format_secret(
    session: &Session,
    secret: &[u8],
    content_type: &str
    ) -> ::Result<SecretStructInput>
{
    let content_type = content_type.to_owned();

    if session.is_encrypted() {
        let mut rng = OsRng {};
        let mut aes_iv = [0;16];
        rng.fill(&mut aes_iv);

        let encrypted_secret = encrypt(secret, &session.get_aes_key()[..], &aes_iv)?;

        // Construct secret struct
        let parameters = aes_iv.to_vec();
        let value = encrypted_secret;

        Ok(SecretStructInput {
            inner: SecretStruct {
                session: session.object_path.clone(),
                parameters,
                value,
                content_type,
            }
        })
    } else {
        // just Plain for now
        let parameters = Vec::new();
        let value = secret.to_vec();

        Ok(SecretStructInput {
            inner: SecretStruct {
                session: session.object_path.clone(),
                parameters,
                value,
                content_type,
            }
        })
    }
}

pub fn exec_prompt(conn: zbus::Connection, prompt: &ObjectPath) -> ::Result<zvariant::OwnedValue> {
    let prompt_interface = PromptInterfaceProxy::new_for_owned(
        conn.clone(),
        SS_DBUS_NAME.to_owned(),
        prompt.to_string(),
        )
        .unwrap();

    let (tx, rx) = channel();

    // create a handler for `completed` signal
    prompt_interface
        .connect_completed(move |dismissed, result| {
            let res = if dismissed {
                Err(SsError::Prompt)
            } else {
                Ok(result)
            };

            // FIXME remove unwrap
            tx.send(res).expect("remove this unwrap");

            Ok(())
        })?;

    // FIXME figure out window_id
    let window_id = "";
    prompt_interface.prompt(window_id)?;

    // waits for next signal and calls the handler
    while prompt_interface.next_signal()?.is_some() {};

    prompt_interface.disconnect_completed()?;

    // FIXME remove unwrap
    rx.recv().expect("remove this unwrap")
}
<commit_msg>notes on signal handling in prompt<commit_after>//Copyright 2016 secret-service-rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

// Contains helpers for:
//   exec_prompt
//   interfaces
//   formatting secrets
//
//   Consider: What else should be in here? Should
//   formatting secrets be in crypto? Should interfaces
//   have their own module?

use error::SsError;
use proxy::prompt::PromptInterfaceProxy;
use proxy::service::ServiceInterfaceProxy;
use session::Session;
use ss::SS_DBUS_NAME;
use ss_crypto::encrypt;
use proxy::SecretStruct;
use proxy::item::SecretStructInput;

use rand::{Rng, rngs::OsRng};
use std::sync::mpsc::channel;
use zvariant::ObjectPath;

// Helper enum for locking
pub(crate) enum LockAction {
    Lock,
    Unlock,
}

pub(crate) fn lock_or_unlock(
    conn: zbus::Connection,
    service_interface: &ServiceInterfaceProxy,
    object_path: &ObjectPath,
    lock_action: LockAction
    ) -> ::Result<()>
{
    let objects = vec![object_path];

    let lock_action_res = match lock_action {
        LockAction::Lock => service_interface.lock(objects)?,
        LockAction::Unlock => service_interface.unlock(objects)?,
    };

    if lock_action_res.object_paths.is_empty() {
        exec_prompt(conn.clone(), &lock_action_res.prompt)?;
    }
    Ok(())
}

pub(crate) fn format_secret(
    session: &Session,
    secret: &[u8],
    content_type: &str
    ) -> ::Result<SecretStructInput>
{
    let content_type = content_type.to_owned();

    if session.is_encrypted() {
        let mut rng = OsRng {};
        let mut aes_iv = [0;16];
        rng.fill(&mut aes_iv);

        let encrypted_secret = encrypt(secret, &session.get_aes_key()[..], &aes_iv)?;

        // Construct secret struct
        let parameters = aes_iv.to_vec();
        let value = encrypted_secret;

        Ok(SecretStructInput {
            inner: SecretStruct {
                session: session.object_path.clone(),
                parameters,
                value,
                content_type,
            }
        })
    } else {
        // just Plain for now
        let parameters = Vec::new();
        let value = secret.to_vec();

        Ok(SecretStructInput {
            inner: SecretStruct {
                session: session.object_path.clone(),
                parameters,
                value,
                content_type,
            }
        })
    }
}

pub fn exec_prompt(conn: zbus::Connection, prompt: &ObjectPath) -> ::Result<zvariant::OwnedValue> {
    let prompt_interface = PromptInterfaceProxy::new_for_owned(
        conn.clone(),
        SS_DBUS_NAME.to_owned(),
        prompt.to_string(),
        )
        .unwrap();

    let (tx, rx) = channel();

    // create a handler for `completed` signal
    prompt_interface
        .connect_completed(move |dismissed, result| {
            let res = if dismissed {
                Err(SsError::Prompt)
            } else {
                Ok(result)
            };

            // FIXME remove unwrap
            tx.send(res).expect("remove this unwrap");

            Ok(())
        })?;

    // FIXME figure out window_id
    let window_id = "";
    prompt_interface.prompt(window_id)?;

    // waits for next signal and calls the handler.
    // If message handled by above handler, `next_signal` returns `Ok(None)`, ending loop.
    while prompt_interface.next_signal()?.is_some() {};

    prompt_interface.disconnect_completed()?;

    // FIXME remove unwrap
    rx.recv().expect("remove this unwrap")
}
<|endoftext|>