<commit_before>use std::ffi::{OsStr, OsString};
use std::path::Path;

use log::warn;

pub struct ExtAttr {
    pub key: OsString,
    pub value: Option<Vec<u8>>,
}

pub fn ext_attrs<'p, P>(path: &'p P) -> std::io::Result<ExtAttrs<'p>>
where
    P: AsRef<Path>,
{
    let iter = xattr::list(&path)?;

    Ok(ExtAttrs {
        path: path.as_ref(),
        iter: iter,
    })
}

pub struct ExtAttrs<'p> {
    path: &'p Path,
    iter: xattr::XAttrs,
}

impl<'p> Iterator for ExtAttrs<'p> {

    type Item = ExtAttr;

    fn next(&mut self) -> Option<ExtAttr> {
        for key in &mut self.iter {
            let value = match ext_attr_value(self.path, &key) {
                Ok(value) => value,
                Err(()) => continue,
            };

            return Some(ExtAttr {
                key: key,
                value: value,
            });
        }

        None
    }
}

fn ext_attr_value<P>(path: P, key: &OsStr) -> Result<Option<Vec<u8>>, ()>
where
    P: AsRef<Path>,
{
    xattr::get(&path, key).map_err(|error| {
        warn! {
            "failed to collect {key:?} of '{path}': {cause}",
            key = key,
            path = path.as_ref().display(),
            cause = error,
        };
    })
}
<commit_msg>Write docs for extended attribute wrappers.<commit_after>//! Unix-specific utilities for working with the filesystem.

use std::ffi::{OsStr, OsString};
use std::path::Path;

use log::warn;

/// An extended attribute of a file.
///
/// On Linux, extended attributes can be obtained using `getfattr` and set with
/// `setfattr` utilities. On macOS, they can be manipulated through `getxattr`
/// and `setxattr` utilities.
///
/// See the [Wikipedia] article for more details.
///
/// [Wikipedia]: https://en.wikipedia.org/wiki/Extended_file_attributes
pub struct ExtAttr {
    /// A name of the extended attribute.
    pub key: OsString,
    /// A value of the extended attribute.
    pub value: Option<Vec<u8>>,
}

/// Returns an iterator over extended attributes of the specified file.
///
/// # Errors
///
/// The function will fail if a list of extended attributes of the file cannot
/// be obtained (e.g. when the file doesn't exist). However, all errors when
/// that can occur when inspecting values for particular attribute are logged
/// and forgotten.
///
/// # Examples
///
/// ```no_run
/// let attrs = rrg::fs::unix::ext_attrs(&"/tmp/foo")
///     .expect("failed to collect extended attributes");
///
/// for attr in attrs {
///     let key = attr.key.to_string_lossy();
///     match attr.value {
///         Some(value) => {
///             let value = std::str::from_utf8(&value)
///                 .expect("failed to convert attribute value");
///
///             println!("{}: {}", key, value);
///         },
///         None => println!("{}", key),
///     }
/// }
/// ```
pub fn ext_attrs<'p, P>(path: &'p P) -> std::io::Result<ExtAttrs<'p>>
where
    P: AsRef<Path>,
{
    let iter = xattr::list(&path)?;

    Ok(ExtAttrs {
        path: path.as_ref(),
        iter: iter,
    })
}

/// Iterator over extended attributes of a file.
///
/// Note that this iterator always returns an attribute. All errors that can
/// occur when obtaining values for particular attributes are swallowed.
///
/// The iterator can be constructed with the [`ext_attrs`] function.
///
/// [`ext_attrs`]: fn.ext_attrs.html
pub struct ExtAttrs<'p> {
    path: &'p Path,
    iter: xattr::XAttrs,
}

impl<'p> Iterator for ExtAttrs<'p> {

    type Item = ExtAttr;

    fn next(&mut self) -> Option<ExtAttr> {
        for key in &mut self.iter {
            let value = match ext_attr_value(self.path, &key) {
                Ok(value) => value,
                Err(()) => continue,
            };

            return Some(ExtAttr {
                key: key,
                value: value,
            });
        }

        None
    }
}

/// Collects value of an extended attribute at the given `key`.
///
/// This is a tiny wrapper around `xattr::get`, but logs and forgets the error
/// (if occurs).
fn ext_attr_value<P>(path: P, key: &OsStr) -> Result<Option<Vec<u8>>, ()>
where
    P: AsRef<Path>,
{
    xattr::get(&path, key).map_err(|error| {
        warn! {
            "failed to collect {key:?} of '{path}': {cause}",
            key = key,
            path = path.as_ref().display(),
            cause = error,
        };
    })
}
<|endoftext|>


<commit_before>// #[macro_use] extern crate lazy_static;

extern crate docopt;
extern crate rusoto;
extern crate rush;
extern crate regex;
extern crate rand;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use std::collections::{HashMap, HashSet};
use rusoto::Region;
use rusoto::ec2::{Ec2Client, DescribeInstancesRequest, Instance};
use rusoto::default_tls_client;
use std::str::FromStr;
use docopt::Docopt;
use regex::Regex;

use rush::ec2_instances::{AshufInfo, write_saved_json};

const USAGE: &'static str = "
Query amazon for a random choice among some set of resources

Display matching resources as a JSON document.

Usage:
  aal [-c | --no-cache] [-d | --debug] [-a <api>...] [-r <region>...] <pattern>
  aal (-h | --help)

Options:
  -h --help             Show this help screen
  -c --no-cache         Bypass the cached resources info
  -r --region=<region>  Region (can be specified more than once) [default: us-east-1 us-west-2]
  -a --api=<api>        Which AWS api [default: ec2]
  -s --ssh-host         Pick a node to ssh to
  -d --debug            whatever stuff I've broken will get done
";

// // A flat structure to make searching for an instance faster, with a
// // link back to the instance.
// #[derive(Clone, Debug, Serialize, Deserialize)]
// struct AshufInfo {
//     instance_id: String,
//     private_ip_addresses: Vec<String>,
//     public_ip_addresses: Vec<String>,
//     state_name: String,
//     launch_time: String,
//     availability_zone: String,
//     image_ami: String,
//     tags: HashMap<String, String>,
// }

fn ip_addresses_of(instance: &Instance) -> (Vec<String>, Vec<String>) {
    /// A host can have either an ENI in vpc, or a private IP address from an EIP (classic)
    /// This function extracts those addresses, and returns two vectors.  The left
    /// vector contains the private addresses of an instance, and the right vector contains the
    /// public addresses of an instance.
    let mut private = HashSet::new();
    let mut public = HashSet::new();

    if let Some(ref network_interfaces) = instance.network_interfaces {
        for interface in network_interfaces {
            if let Some(ref addr) = interface.private_ip_address {
                private.insert(addr.clone());
            }
        }
    }

    instance.private_ip_address.as_ref().map(|addr| private.insert(addr.clone()));
    instance.public_ip_address.as_ref().map(|addr| public.insert(addr.clone()));

    (vec!(private.into_iter().collect()), vec!(public.into_iter().collect()))
}

fn tags_of(instance: &Instance) -> HashMap<String, String> {
    /// Tags are stored as inconvenient pairs of {"Name": "name", "Value": "Value"}
    /// turn them into simpler key/value map here
    let mut tags = HashMap::new();
    if let Some(ref instance_tags) = instance.tags {
        for tag in instance_tags {
             if let (&Some(ref key), &Some(ref val)) = (&tag.key, &tag.value) {
                 tags.insert(key.clone(), val.clone());
             }
         }
     }
    tags
}

fn ashuf_info_list(instances: Vec<Instance>) -> Vec<AshufInfo> {
    /// Take just the data we want for the AshufInfo struct from the
    /// rusoto::ec2::Instance type, and return a vector of `AshufInfo`
    ///
    /// All data is copied from the instances provided, they are consumed
    /// here.
    let mut limited_instances: Vec<AshufInfo> = Vec::new();
    for inst in instances {
        // println!("This instance is {:?}",  inst);
        let (private_addrs, public_addrs) = ip_addresses_of(&inst);
        let tags = tags_of(&inst);
        // println!("{:?}", addrs);
        let new_asi = AshufInfo {
            instance_id: String::from(inst.instance_id.unwrap()),
            private_ip_addresses: private_addrs,
            public_ip_addresses: public_addrs,
            state_name: String::from(inst.state.unwrap().name.unwrap()),
            launch_time: String::from(inst.launch_time.unwrap()),
            availability_zone: String::from(inst.placement.unwrap().availability_zone.unwrap()),
            image_ami: String::from(inst.image_id.unwrap()),
            tags: tags,
        };
        limited_instances.push(new_asi);
    }
    limited_instances
}

// returns OK on the left, and Not OK on the right.
// Let's define that so that on the left are matched instances,
// and the right  is unmatched instances.
fn partition_matches(rexpr: &Regex, tag: &String, instances: Vec<AshufInfo>) -> (Vec<AshufInfo>,  Vec<AshufInfo>) {
    let (matched, unmatched) = instances
        .into_iter()
        .partition(|inst| {
            if let Some(tval) = inst.tags.get(tag) {
                if rexpr.is_match(tval) {  // Match on the value (assuming it can't be None?)
                    // println!("Matched {:?}", tval);
                    true
                } else {
                    false
                }
            } else {
                false
            }
        });
    (matched, unmatched)
}

// Bring
fn instances_matching_regex(pattern: String, interesting_tags: Vec<String>, instances: Vec<AshufInfo>) -> Vec<AshufInfo> {
    let rexpr = Regex::new(&pattern).unwrap();
    let mut unmatched_instances = Vec::new();
    let mut matched_instances = Vec::new();
    unmatched_instances.extend_from_slice(instances.as_slice());

    for ref tag in interesting_tags {
        let (m, u) = partition_matches(&rexpr, tag, unmatched_instances);
        // Re-bind unmatched instances for the next loop
        unmatched_instances = u;
        matched_instances.extend_from_slice(m.as_slice());
    }

    matched_instances
}

fn main() {
    let version = "0.1.0".to_owned();
    let parsed_cmdline = Docopt::new(USAGE)
        .and_then(|d| d.version(Some(version)).parse())
        .unwrap_or_else(|e| e.exit());
    let debug = parsed_cmdline.get_bool("-d");
    let pattern = parsed_cmdline.get_str("<pattern>").to_string();
    if debug {
        println!("Command line parsed to {:?}", parsed_cmdline);
        println!("Pattern is {:?}", pattern);
    };
    let creds = rush::auth::credentials_provider(None, None);
    // XXx when ready, map over the regions provided and cache those
    // so they can be combined afterwards.  But for now, let's do one
    // region.
    let r = parsed_cmdline.get_vec("-r");

    let reg = Region::from_str(r[0]).unwrap();
    let client = Ec2Client::new(default_tls_client().unwrap(), creds, reg);
    let mut ec2_request_input = DescribeInstancesRequest::default();
    ec2_request_input.instance_ids = None;
    // ec2_request_input.instance_ids = Some(vec!["something".into()]);

    let mut limited_info = Vec::new();

    match client.describe_instances(&ec2_request_input) {
        Ok(response) => {
            let instances = rush::ec2_instances::ec2_res_to_instances(response.reservations.unwrap());
            // if parsed_cmdline.get_bool("-d") {
            //     println!("{:?}", instances);
            // };
            limited_info.extend(ashuf_info_list(instances));
            // println!("{:?}", limited_info.len());

        },
        Err(error) => {
            println!("Error: {:?}", error);
        }
    }

    let tags = vec!["Name".to_string(), "Tier".to_string()];
    let matches = instances_matching_regex(pattern, tags, limited_info);
    // for m in matches.as_ref() {
    //    println!("{}", m.ip_addresses[0].clone());
    // }
    let matched_json = serde_json::to_string_pretty(&matches).expect("Couldn't serialize config");
    // Now write the cache
    match write_saved_json(1, &matches) {
        Ok(_) => println!("{}", matched_json),
        Err(result) => println!("{:?}", result)
    };
}
<commit_msg>Add flags for accounts and starts on outputs<commit_after>// #[macro_use] extern crate lazy_static;

extern crate docopt;
extern crate rusoto_core;
extern crate rusoto_ec2;
extern crate rush;
extern crate regex;
extern crate rand;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use std::collections::{HashMap, HashSet};
use rusoto_core::{Region, default_tls_client};
use rusoto_ec2::{Ec2, Ec2Client, DescribeInstancesRequest, Instance};
use std::str::FromStr;
use std::env;
use docopt::Docopt;
use regex::Regex;

use rush::ec2_instances::{AshufInfo, write_saved_json, ec2_cached_data};

const USAGE: &'static str = "
Query amazon for a random choice among some set of resources

Display matching resources as a JSON document.

Usage:
  aal [-c | --no-cache] [-e <env_name>]  [-d | --debug] [-a <api>...] [-r <region>...] [-m | --mode <output_mode>] <pattern>
  aal (-h | --help)

Options:
  -h --help                 Show this help screen
  -c --no-cache             Bypass the cached resources info
  -e --env-name=<env_name>  The environment variable containing the name of this account [default: AWS_ACCOUNT_ID]
  -r --region=<region>      Region (can be specified more than once) [default: us-east-1 us-west-2]
  -a --api=<api>            Which AWS api [default: ec2]
  -s --ssh-host             Pick a node to ssh to
  -d --debug                whatever stuff I've broken will get done
  -m --mode                 Output mode [default: ip_private_line]
";

// // A flat structure to make searching for an instance faster, with a
// // link back to the instance.
// #[derive(Clone, Debug, Serialize, Deserialize)]
// struct AshufInfo {
//     instance_id: String,
//     private_ip_addresses: Vec<String>,
//     public_ip_addresses: Vec<String>,
//     state_name: String,
//     launch_time: String,
//     availability_zone: String,
//     image_ami: String,
//     tags: HashMap<String, String>,
// }

fn ip_addresses_of(instance: &Instance) -> (Vec<String>, Vec<String>) {
    /// A host can have either an ENI in vpc, or a private IP address from an EIP (classic)
    /// This function extracts those addresses, and returns two vectors.  The left
    /// vector contains the private addresses of an instance, and the right vector contains the
    /// public addresses of an instance.
    let mut private = HashSet::new();
    let mut public = HashSet::new();

    if let Some(ref network_interfaces) = instance.network_interfaces {
        for interface in network_interfaces {
            if let Some(ref addr) = interface.private_ip_address {
                private.insert(addr.clone());
            }
        }
    }

    instance.private_ip_address.as_ref().map(|addr| private.insert(addr.clone()));
    instance.public_ip_address.as_ref().map(|addr| public.insert(addr.clone()));

    (vec!(private.into_iter().collect()), vec!(public.into_iter().collect()))
}

fn tags_of(instance: &Instance) -> HashMap<String, String> {
    /// Tags are stored as inconvenient pairs of {"Name": "name", "Value": "Value"}
    /// turn them into simpler key/value map here
    let mut tags = HashMap::new();
    if let Some(ref instance_tags) = instance.tags {
        for tag in instance_tags {
             if let (&Some(ref key), &Some(ref val)) = (&tag.key, &tag.value) {
                 tags.insert(key.clone(), val.clone());
             }
         }
     }
    tags
}

fn ashuf_info_list(instances: Vec<Instance>) -> Vec<AshufInfo> {
    /// Take just the data we want for the AshufInfo struct from the
    /// rusoto::ec2::Instance type, and return a vector of `AshufInfo`
    ///
    /// All data is copied from the instances provided, they are consumed
    /// here.
    let mut limited_instances: Vec<AshufInfo> = Vec::new();
    for inst in instances {
        // println!("This instance is {:?}",  inst);
        let (private_addrs, public_addrs) = ip_addresses_of(&inst);
        let tags = tags_of(&inst);
        // println!("{:?}", addrs);
        let new_asi = AshufInfo {
            instance_id: String::from(inst.instance_id.unwrap()),
            private_ip_addresses: private_addrs,
            public_ip_addresses: public_addrs,
            state_name: String::from(inst.state.unwrap().name.unwrap()),
            launch_time: String::from(inst.launch_time.unwrap()),
            availability_zone: String::from(inst.placement.unwrap().availability_zone.unwrap()),
            image_ami: String::from(inst.image_id.unwrap()),
            tags: tags,
        };
        limited_instances.push(new_asi);
    }
    limited_instances
}

// returns OK on the left, and Not OK on the right.
// Let's define that so that on the left are matched instances,
// and the right  is unmatched instances.
fn partition_matches(rexpr: &Regex, tag: &String, instances: Vec<AshufInfo>) -> (Vec<AshufInfo>,  Vec<AshufInfo>) {
    let (matched, unmatched) = instances
        .into_iter()
        .partition(|inst| {
            if let Some(tval) = inst.tags.get(tag) {
                if rexpr.is_match(tval) {  // Match on the value (assuming it can't be None?)
                    // println!("Matched {:?}", tval);
                    true
                } else {
                    false
                }
            } else {
                false
            }
        });
    (matched, unmatched)
}

// Bring
fn instances_matching_regex(pattern: String, interesting_tags: Vec<String>, instances: Vec<AshufInfo>) -> Vec<AshufInfo> {
    let rexpr = Regex::new(&pattern).unwrap();
    let mut unmatched_instances = Vec::new();
    let mut matched_instances = Vec::new();
    unmatched_instances.extend_from_slice(instances.as_slice());

    for ref tag in interesting_tags {
        let (m, u) = partition_matches(&rexpr, tag, unmatched_instances);
        // Re-bind unmatched instances for the next loop
        unmatched_instances = u;
        matched_instances.extend_from_slice(m.as_slice());
    }

    matched_instances
}

fn print_ip_private_line(results) {
    /// prints the publuc

fn main() {
    let version = "0.1.0".to_owned();
    let parsed_cmdline = Docopt::new(USAGE)
        .and_then(|d| d.version(Some(version)).parse())
        .unwrap_or_else(|e| e.exit());
    let debug = parsed_cmdline.get_bool("-d");
    let pattern = parsed_cmdline.get_str("<pattern>").to_string();
    if debug {
        println!("Command line parsed to {:?}", parsed_cmdline);
        println!("Pattern is {:?}", pattern);
    };
    let creds = rush::auth::credentials_provider(None, None);
    // XXx when ready, map over the regions provided and cache those
    // so they can be combined afterwards.  But for now, let's do one
    // region.
    let r = parsed_cmdline.get_vec("-r");
    let aws_id = match(env::var(parsed_cmdline.get_str("-e"))) {
        Ok(val) => val,
        Err(val) => "default".to_string()
    };

    let reg = Region::from_str(r[0]).unwrap();
    let client = Ec2Client::new(default_tls_client().unwrap(), creds, reg);
    let mut ec2_request_input = DescribeInstancesRequest::default();
    ec2_request_input.instance_ids = None;
    let mut limited_info = Vec::new();

    match(ec2_cached_data("/tmp".to_string(), &aws_id, 300)) {
        Ok(instances) => {
            println!("I'm using cache data");
            limited_info.extend(instances);
        },
        Err(_) => {
            println!("I'm in the error case, using cache data");
            match client.describe_instances(&ec2_request_input) {
                Ok(response) => {
                    let instances = rush::ec2_instances::ec2_res_to_instances(response.reservations.unwrap());
                    limited_info.extend(ashuf_info_list(instances));
                    match write_saved_json(&aws_id, &limited_info) {
                        Ok(msg) => println!("{}", msg),
                        Err(what_happened) => println!("{}", what_happened),
                    }
                },
                Err(error) => {
                    println!("Error: {:?}", error);
                }
            }
        }
    };

    let tags = vec!["Name".to_string(), "Tier".to_string()];
    let matches = instances_matching_regex(pattern, tags, limited_info);
    let matched_json = serde_json::to_string_pretty(&matches).expect("Couldn't serialize config");
    println!("Matches: {:?}", matches);
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fs::{File, OpenOptions};
use std::io::BufReader;
use std::io::{prelude::*, SeekFrom};
use std::path::{Path, PathBuf};
use std::process;

use libsignify::{
    consts::DEFAULT_KDF_ROUNDS, Codeable, NewKeyOpts, PrivateKey, PublicKey, Signature,
};

use clap::{IntoApp, Parser};

#[derive(Parser)]
#[clap(
    name = "signify",
    override_usage = r#"signify -h
    signify -G [-n] [-c <comment>] -p <pubkey> -s <seckey>
    signify -S [-e] [-x <sigfile>] -s <seckey> -m <message>
    signify -V [-e] [-x <sigfile>] -p <pubkey> -m <message>"#
)]
struct Args {
    /// Generate a new keypair
    #[clap(short = 'G')]
    generate: bool,
    /// Sign the specified message file
    #[clap(short = 'S')]
    sign: bool,
    /// Verify a message
    #[clap(short = 'V')]
    verify: bool,
    /// Public key produced by -G, and used by -V to check a signature
    #[clap(short, parse(from_os_str))]
    pubkey: Option<PathBuf>,
    /// Secret (private) key produced by -G, and used by -S to sign a message
    #[clap(short, parse(from_os_str))]
    seckey: Option<PathBuf>,
    /// Do not ask for a passphrase during key generation. Otherwise, signify
    /// will prompt the user for a passphrase to protect the secret key
    #[clap(short = 'n')]
    skip_key_encryption: bool,
    /// The file containing the message to create a signature over
    #[clap(short, parse(from_os_str))]
    message_path: Option<PathBuf>,
    /// When signing, embed the message after the signature. When verifying,
    /// extract the message from the signature
    #[clap(short)]
    embed_message: bool,
    /// The signature file to create or verify. The default is <message>.sig
    #[clap(short = 'x', parse(from_os_str))]
    signature_path: Option<PathBuf>,
    /// Specify the comment to be added during key generation
    #[clap(short)]
    comment: Option<String>,
}

fn write_base64_file<C: Codeable>(
    file: &mut File,
    comment: &str,
    data: &C,
) -> Result<(), Box<dyn Error>> {
    let contents = data.to_file_encoding(comment);
    file.write_all(&contents)?;

    Ok(())
}

// Annoyingly `p.with_extension("sig")` will turn `foo.bar` into `foo.sig`. This
// avoids that issue (and without requiring the path be UTF-8), but is kind of
// tedious. Note that `ext` should be something like `"sig"` and not `".sig"`.
fn add_extension(p: impl Into<PathBuf>, ext: &str) -> PathBuf {
    use std::ffi::OsString;
    let mut path: PathBuf = p.into();
    let mut name: OsString = path.file_name().unwrap_or_default().to_owned();
    name.push(".");
    name.push(ext);
    path.set_file_name(name);
    path
}

#[test]
fn test_add_extension() {
    #[track_caller]
    fn check(p: impl AsRef<Path>, e: &str, want: impl AsRef<Path>) {
        let p = p.as_ref();
        let want = want.as_ref();
        assert_eq!(add_extension(p, e), want);
    }
    check("foo", "sig", "foo.sig");
    check("foo.bar.baz", "sig", "foo.bar.baz.sig");
    check("/a/b/c/foo.bar.baz", "sig", "/a/b/c/foo.bar.baz.sig");
    check("/a/b/c/foo", "sig", "/a/b/c/foo.sig");

    check("foo.bar.baz", "a.b", "foo.bar.baz.a.b");
    check("foo", "a.b", "foo.a.b");
    check("/a/b/c/foo.bar.baz", "a.b", "/a/b/c/foo.bar.baz.a.b");
    check("/a/b/c/foo", "a.b", "/a/b/c/foo.a.b");
}

fn read_base64_file<C: Codeable, R: Read>(
    reader: &mut BufReader<R>,
) -> Result<(C, u64), Box<dyn Error>> {
    let mut contents = String::with_capacity(1024);
    // Optimization: Read the two lines that have the comment and well structured data
    // instead of the entire file in case the message was large and embedded.
    reader.read_line(&mut contents)?;
    reader.read_line(&mut contents)?;

    let read = C::from_base64(&contents)?;
    Ok(read)
}

fn verify(
    pubkey_path: &Path,
    msg_path: &Path,
    signature_path: Option<PathBuf>,
    embed: bool,
) -> Result<(), Box<dyn Error>> {
    let mut pubkey_file = BufReader::new(File::open(pubkey_path)?);
    let public_key: PublicKey = read_base64_file(&mut pubkey_file)?.0;

    let signature_path = match signature_path {
        Some(path) => path,
        None => add_extension(msg_path, "sig"),
    };

    let mut sig_data = BufReader::new(File::open(&signature_path)?);

    let (signature, bytes_read): (Signature, u64) = read_base64_file(&mut sig_data)?;

    let mut msg = vec![];

    if embed {
        // Jump around past the well structured signify message to the
        // embedded contents.
        sig_data.seek(SeekFrom::Start(bytes_read))?;
        sig_data.read_to_end(&mut msg)?;
    } else {
        let mut msg_file = File::open(msg_path)?;
        msg_file.read_to_end(&mut msg)?;
    }

    public_key
        .verify(&msg, &signature)
        .map(|_| {
            println!("Signature Verified");
        })
        .map_err(Into::into)
}

fn sign(
    private_key_path: &Path,
    msg_path: &Path,
    signature_path: Option<PathBuf>,
    embed: bool,
) -> Result<(), Box<dyn std::error::Error>> {
    let mut secret_key = BufReader::new(File::open(private_key_path)?);
    let mut secret_key: PrivateKey = read_base64_file(&mut secret_key)?.0;

    if secret_key.is_encrypted() {
        let passphrase = read_passphrase(false)?;
        secret_key.decrypt_with_password(&passphrase)?;
    }

    let mut msg_file = File::open(&msg_path)?;
    let mut msg = vec![];
    msg_file.read_to_end(&mut msg)?;

    let signature_path = match signature_path {
        Some(path) => path,
        None => add_extension(msg_path, "sig"),
    };

    let sig = secret_key.sign(&msg);

    let sig_comment = "signature from signify secret key";

    let mut file = OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(&signature_path)?;

    write_base64_file(&mut file, sig_comment, &sig)?;

    if embed {
        file.write_all(&msg)?;
    }

    Ok(())
}

fn read_passphrase(confirm: bool) -> Result<String, Box<dyn std::error::Error>> {
    let passphrase = rpassword::prompt_password_stdout("passphrase: ")?;

    if confirm {
        let confirm_passphrase = rpassword::prompt_password_stdout("confirm passphrase: ")?;

        if passphrase != confirm_passphrase {
            return Err("passwords don't match".into());
        }
    }

    Ok(passphrase)
}

fn generate(
    pubkey_path: &Path,
    privkey_path: &Path,
    comment: Option<&str>,
    kdfrounds: Option<u32>,
) -> Result<(), Box<dyn std::error::Error>> {
    let comment = comment.unwrap_or("signify");

    let derivation_info = match kdfrounds {
        Some(kdf_rounds) => {
            let passphrase = read_passphrase(true)?;
            NewKeyOpts::Encrypted {
                passphrase,
                kdf_rounds,
            }
        }
        None => NewKeyOpts::NoEncryption,
    };

    // Store the private key
    let mut rng = rand_core::OsRng {};
    let private_key = PrivateKey::generate(&mut rng, derivation_info)?;

    let priv_comment = format!("{} secret key", comment);
    let mut file = OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(privkey_path)?;

    write_base64_file(&mut file, &priv_comment, &private_key)?;

    // Store public key
    let public_key = private_key.public();

    let pub_comment = format!("{} public key", comment);
    let mut file = OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(pubkey_path)?;

    write_base64_file(&mut file, &pub_comment, &public_key)?;

    Ok(())
}

fn human<T>(res: Result<T, Box<dyn std::error::Error>>) -> T {
    match res {
        Ok(val) => val,
        Err(e) => {
            println!("error: {}", e);
            process::exit(1);
        }
    }
}

fn unwrap_path<T>(kind: &'static str, path: Option<T>) -> T {
    match path {
        Some(p) => p,
        None => {
            println!("missing path to {}", kind);
            process::exit(1)
        }
    }
}

fn main() {
    let args = Args::parse();

    if args.verify {
        let public_key = unwrap_path("pubkey", args.pubkey);
        let message = unwrap_path("message", args.message_path);

        human(verify(
            &public_key,
            &message,
            args.signature_path,
            args.embed_message,
        ));

        return;
    }

    if args.generate {
        let public_key = unwrap_path("pubkey", args.pubkey);
        let private_key = unwrap_path("seckey", args.seckey);
        let rounds = if args.skip_key_encryption {
            None
        } else {
            Some(DEFAULT_KDF_ROUNDS)
        };

        human(generate(
            &public_key,
            &private_key,
            args.comment.as_deref(),
            rounds,
        ));

        return;
    }

    if args.sign {
        let private_key = unwrap_path("seckey", args.seckey);
        let msg_path = unwrap_path("message", args.message_path);

        human(sign(
            &private_key,
            &msg_path,
            args.signature_path,
            args.embed_message,
        ));

        return;
    }

    // No command specified.
    println!("{}", Args::into_app().render_usage());
}
<commit_msg>Update signify/src/main.rs<commit_after>use std::error::Error;
use std::fs::{File, OpenOptions};
use std::io::BufReader;
use std::io::{prelude::*, SeekFrom};
use std::path::{Path, PathBuf};
use std::process;

use libsignify::{
    consts::DEFAULT_KDF_ROUNDS, Codeable, NewKeyOpts, PrivateKey, PublicKey, Signature,
};

use clap::{IntoApp, Parser};

#[derive(Parser)]
#[clap(
    name = "signify",
    override_usage = r#"signify -h
    signify -G [-n] [-c <comment>] -p <pubkey> -s <seckey>
    signify -S [-e] [-x <sigfile>] -s <seckey> -m <message>
    signify -V [-e] [-x <sigfile>] -p <pubkey> -m <message>"#
)]
struct Args {
    /// Generate a new keypair
    #[clap(short = 'G')]
    generate: bool,
    /// Sign the specified message file
    #[clap(short = 'S')]
    sign: bool,
    /// Verify a message
    #[clap(short = 'V')]
    verify: bool,
    /// Public key produced by -G, and used by -V to check a signature
    #[clap(short, parse(from_os_str))]
    pubkey: Option<PathBuf>,
    /// Secret (private) key produced by -G, and used by -S to sign a message
    #[clap(short, parse(from_os_str))]
    seckey: Option<PathBuf>,
    /// Do not ask for a passphrase during key generation. Otherwise, signify
    /// will prompt the user for a passphrase to protect the secret key
    #[clap(short = 'n')]
    skip_key_encryption: bool,
    /// The file containing the message to create a signature over or to the one to verify with an existing signature
    #[clap(short, parse(from_os_str))]
    message_path: Option<PathBuf>,
    /// When signing, embed the message after the signature. When verifying,
    /// extract the message from the signature
    #[clap(short)]
    embed_message: bool,
    /// The signature file to create or verify. The default is <message>.sig
    #[clap(short = 'x', parse(from_os_str))]
    signature_path: Option<PathBuf>,
    /// Specify the comment to be added during key generation
    #[clap(short)]
    comment: Option<String>,
}

fn write_base64_file<C: Codeable>(
    file: &mut File,
    comment: &str,
    data: &C,
) -> Result<(), Box<dyn Error>> {
    let contents = data.to_file_encoding(comment);
    file.write_all(&contents)?;

    Ok(())
}

// Annoyingly `p.with_extension("sig")` will turn `foo.bar` into `foo.sig`. This
// avoids that issue (and without requiring the path be UTF-8), but is kind of
// tedious. Note that `ext` should be something like `"sig"` and not `".sig"`.
fn add_extension(p: impl Into<PathBuf>, ext: &str) -> PathBuf {
    use std::ffi::OsString;
    let mut path: PathBuf = p.into();
    let mut name: OsString = path.file_name().unwrap_or_default().to_owned();
    name.push(".");
    name.push(ext);
    path.set_file_name(name);
    path
}

#[test]
fn test_add_extension() {
    #[track_caller]
    fn check(p: impl AsRef<Path>, e: &str, want: impl AsRef<Path>) {
        let p = p.as_ref();
        let want = want.as_ref();
        assert_eq!(add_extension(p, e), want);
    }
    check("foo", "sig", "foo.sig");
    check("foo.bar.baz", "sig", "foo.bar.baz.sig");
    check("/a/b/c/foo.bar.baz", "sig", "/a/b/c/foo.bar.baz.sig");
    check("/a/b/c/foo", "sig", "/a/b/c/foo.sig");

    check("foo.bar.baz", "a.b", "foo.bar.baz.a.b");
    check("foo", "a.b", "foo.a.b");
    check("/a/b/c/foo.bar.baz", "a.b", "/a/b/c/foo.bar.baz.a.b");
    check("/a/b/c/foo", "a.b", "/a/b/c/foo.a.b");
}

fn read_base64_file<C: Codeable, R: Read>(
    reader: &mut BufReader<R>,
) -> Result<(C, u64), Box<dyn Error>> {
    let mut contents = String::with_capacity(1024);
    // Optimization: Read the two lines that have the comment and well structured data
    // instead of the entire file in case the message was large and embedded.
    reader.read_line(&mut contents)?;
    reader.read_line(&mut contents)?;

    let read = C::from_base64(&contents)?;
    Ok(read)
}

fn verify(
    pubkey_path: &Path,
    msg_path: &Path,
    signature_path: Option<PathBuf>,
    embed: bool,
) -> Result<(), Box<dyn Error>> {
    let mut pubkey_file = BufReader::new(File::open(pubkey_path)?);
    let public_key: PublicKey = read_base64_file(&mut pubkey_file)?.0;

    let signature_path = match signature_path {
        Some(path) => path,
        None => add_extension(msg_path, "sig"),
    };

    let mut sig_data = BufReader::new(File::open(&signature_path)?);

    let (signature, bytes_read): (Signature, u64) = read_base64_file(&mut sig_data)?;

    let mut msg = vec![];

    if embed {
        // Jump around past the well structured signify message to the
        // embedded contents.
        sig_data.seek(SeekFrom::Start(bytes_read))?;
        sig_data.read_to_end(&mut msg)?;
    } else {
        let mut msg_file = File::open(msg_path)?;
        msg_file.read_to_end(&mut msg)?;
    }

    public_key
        .verify(&msg, &signature)
        .map(|_| {
            println!("Signature Verified");
        })
        .map_err(Into::into)
}

fn sign(
    private_key_path: &Path,
    msg_path: &Path,
    signature_path: Option<PathBuf>,
    embed: bool,
) -> Result<(), Box<dyn std::error::Error>> {
    let mut secret_key = BufReader::new(File::open(private_key_path)?);
    let mut secret_key: PrivateKey = read_base64_file(&mut secret_key)?.0;

    if secret_key.is_encrypted() {
        let passphrase = read_passphrase(false)?;
        secret_key.decrypt_with_password(&passphrase)?;
    }

    let mut msg_file = File::open(&msg_path)?;
    let mut msg = vec![];
    msg_file.read_to_end(&mut msg)?;

    let signature_path = match signature_path {
        Some(path) => path,
        None => add_extension(msg_path, "sig"),
    };

    let sig = secret_key.sign(&msg);

    let sig_comment = "signature from signify secret key";

    let mut file = OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(&signature_path)?;

    write_base64_file(&mut file, sig_comment, &sig)?;

    if embed {
        file.write_all(&msg)?;
    }

    Ok(())
}

fn read_passphrase(confirm: bool) -> Result<String, Box<dyn std::error::Error>> {
    let passphrase = rpassword::prompt_password_stdout("passphrase: ")?;

    if confirm {
        let confirm_passphrase = rpassword::prompt_password_stdout("confirm passphrase: ")?;

        if passphrase != confirm_passphrase {
            return Err("passwords don't match".into());
        }
    }

    Ok(passphrase)
}

fn generate(
    pubkey_path: &Path,
    privkey_path: &Path,
    comment: Option<&str>,
    kdfrounds: Option<u32>,
) -> Result<(), Box<dyn std::error::Error>> {
    let comment = comment.unwrap_or("signify");

    let derivation_info = match kdfrounds {
        Some(kdf_rounds) => {
            let passphrase = read_passphrase(true)?;
            NewKeyOpts::Encrypted {
                passphrase,
                kdf_rounds,
            }
        }
        None => NewKeyOpts::NoEncryption,
    };

    // Store the private key
    let mut rng = rand_core::OsRng {};
    let private_key = PrivateKey::generate(&mut rng, derivation_info)?;

    let priv_comment = format!("{} secret key", comment);
    let mut file = OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(privkey_path)?;

    write_base64_file(&mut file, &priv_comment, &private_key)?;

    // Store public key
    let public_key = private_key.public();

    let pub_comment = format!("{} public key", comment);
    let mut file = OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(pubkey_path)?;

    write_base64_file(&mut file, &pub_comment, &public_key)?;

    Ok(())
}

fn human<T>(res: Result<T, Box<dyn std::error::Error>>) -> T {
    match res {
        Ok(val) => val,
        Err(e) => {
            println!("error: {}", e);
            process::exit(1);
        }
    }
}

fn unwrap_path<T>(kind: &'static str, path: Option<T>) -> T {
    match path {
        Some(p) => p,
        None => {
            println!("missing path to {}", kind);
            process::exit(1)
        }
    }
}

fn main() {
    let args = Args::parse();

    if args.verify {
        let public_key = unwrap_path("pubkey", args.pubkey);
        let message = unwrap_path("message", args.message_path);

        human(verify(
            &public_key,
            &message,
            args.signature_path,
            args.embed_message,
        ));

        return;
    }

    if args.generate {
        let public_key = unwrap_path("pubkey", args.pubkey);
        let private_key = unwrap_path("seckey", args.seckey);
        let rounds = if args.skip_key_encryption {
            None
        } else {
            Some(DEFAULT_KDF_ROUNDS)
        };

        human(generate(
            &public_key,
            &private_key,
            args.comment.as_deref(),
            rounds,
        ));

        return;
    }

    if args.sign {
        let private_key = unwrap_path("seckey", args.seckey);
        let msg_path = unwrap_path("message", args.message_path);

        human(sign(
            &private_key,
            &msg_path,
            args.signature_path,
            args.embed_message,
        ));

        return;
    }

    // No command specified.
    println!("{}", Args::into_app().render_usage());
}
<|endoftext|>


<commit_before>//! This module serves as the entry point into Xt's main binary.

// This file is part of Xt.

// This is the Xt text editor; it edits text.
// Copyright (C) 2016-2017  The Xt Developers

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

// This program 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
// General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see
// <http://www.gnu.org/licenses/>.

extern crate clap;
extern crate xt_core as xt;

#[macro_use]
extern crate slog;
extern crate slog_term;

use clap::{App, Arg, ArgMatches, SubCommand};
use xt::logging::init_logger;
use xt::utils::get_version;

fn retrieve_arguments() -> ArgMatches<'static> {
    App::new("xt-core")
        .version(get_version())
        .author("Dom Rodriguez <shymega@shymega.org.uk>")
        .about("Core backend for Xt.")
        .arg(
            Arg::with_name("verbose")
                .short("v")
                .multiple(true)
                .required(false)
                .help("Set the level of logging verbosity"),
        )
        .get_matches()
}

fn main() {
    let cargs = retrieve_arguments();

    let log = init_logger();

    error!(log, "This program is unable to start right now.");
}
<commit_msg>Improving bin/xtc.rs formatting (Rustfmt)<commit_after>//! This module serves as the entry point into Xt's main binary.

// This file is part of Xt.

// This is the Xt text editor; it edits text.
// Copyright (C) 2016-2017  The Xt Developers

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

// This program 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
// General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see
// <http://www.gnu.org/licenses/>.

extern crate clap;
extern crate xt_core as xt;

#[macro_use]
extern crate slog;
extern crate slog_term;

use clap::{App, Arg, ArgMatches, SubCommand};
use xt::logging::init_logger;
use xt::utils::get_version;

fn retrieve_arguments() -> ArgMatches<'static> {
    App::new("xt-core")
        .version(get_version())
        .author("Dom Rodriguez <shymega@shymega.org.uk>")
        .about("Core backend for Xt.")
        .arg(
            Arg::with_name("verbose")
                .short("v")
                .multiple(true)
                .required(false)
                .help("Set the level of logging verbosity"),
        )
        .subcommand(
            SubCommand::with_name("spawn").help("Spawn a instance of Xt"),
        )
        .get_matches()
}

fn main() {
    let _cargs = retrieve_arguments();

    let log = init_logger();

    trace!(
        log,
        "Xt-Core loading. Version: {}",
        env!("GIT_HASH")
    );

    error!(
        log,
        "Xt (core0 is not ready for every-day use yet. I'm very sorry."
    );
}
<|endoftext|>


<commit_before>//!Handler context and request body reading extensions.
//!
//!#Context
//!
//!The [`Context`][context] contains all the input data for the request
//!handlers, as well as some utilities. This is where request data, like
//!headers, client address and the request body can be retrieved from and it
//!can safely be picked apart, since its ownership is transferred to the
//!handler.
//!
//!##Accessing Headers
//!
//!The headers are stored in the `headers` field. See the [`Headers`][headers]
//!struct for more information about how to access them.
//!
//!```
//!use rustful::{Context, Response};
//!use rustful::header::UserAgent;
//!
//!fn my_handler(context: Context, response: Response) {
//!    if let Some(&UserAgent(ref user_agent)) = context.headers.get() {
//!        response.send(format!("got user agent string \"{}\"", user_agent));
//!    } else {
//!        response.send("no user agent string provided");
//!    }
//!}
//!```
//!
//!##Path Variables
//!
//!A router may collect variable data from paths (for example `id` in
//!`/products/:id`). The values from these variables can be accessed through
//!the `variables` field.
//!
//!```
//!use rustful::{Context, Response};
//!
//!fn my_handler(context: Context, response: Response) {
//!    if let Some(id) = context.variables.get("id") {
//!        response.send(format!("asking for product with id \"{}\"", id));
//!    } else {
//!        //This will usually not happen, unless the handler is also
//!        //assigned to a path without the `id` variable
//!        response.send("no id provided");
//!    }
//!}
//!```
//!
//!##Other URL Parts
//!
//! * Query variables (`http://example.com?a=b&c=d`) can be found in the
//!`query` field and they are accessed in exactly the same fashion as path
//!variables are used.
//!
//! * The fragment (`http://example.com#foo`) is also parsed and can be
//!accessed through `fragment` as an optional `String`.
//!
//!##Logging
//!
//!Rustful has a built in logging infrastructure and it is made available to
//!handlers through the `log` field. This provides logging and error reporting
//!in a unified and more controlled fashion than what panics and `println!`
//!gives. See the [`log`][log] module for more information about the standard
//!alternatives.
//!
//!```
//!# fn something_that_may_fail() -> Result<&'static str, &'static str> { Ok("yo") }
//!use rustful::{Context, Response};
//!use rustful::StatusCode::InternalServerError;
//!
//!fn my_handler(context: Context, mut response: Response) {
//!    match something_that_may_fail() {
//!        Ok(res) => response.send(res),
//!        Err(e) => {
//!            context.log.error(&format!("it failed! {}", e));
//!            response.set_status(InternalServerError);
//!        }
//!    }
//!}
//!```
//!
//!##Global Data
//!
//!There is also infrastructure for globally accessible data, that can be
//!accessed through the `global` field. This is meant to provide a place for
//!things like database connections or cached data that should be available to
//!all handlers. The storage space itself is immutable when the server has
//!started, so the only way to change it is through some kind of inner
//!mutability.
//!
//!```
//!use rustful::{Context, Response};
//!use rustful::StatusCode::InternalServerError;
//!
//!fn my_handler(context: Context, mut response: Response) {
//!    if let Some(some_wise_words) = context.global.get::<&str>() {
//!        response.send(format!("food for thought: {}", some_wise_words));
//!    } else {
//!        context.log.error("there should be a string literal in `global`");
//!        response.set_status(InternalServerError);
//!    }
//!}
//!```
//!
//!##Request Body
//!
//!The body will not be read in advance, unlike the other parts of the
//!request. It is instead available as a `BodyReader` in the field `body`,
//!through which it can be read and parsed as various data formats, like JSON
//!and query strings. The documentation for [`BodyReader`][body_reader] gives
//!more examples.
//!
//!```
//!use std::io::{BufReader, BufRead};
//!use rustful::{Context, Response};
//!
//!fn my_handler(context: Context, response: Response) {
//!    let mut numbered_lines = BufReader::new(context.body).lines().enumerate();
//!    let mut writer = response.into_chunked();
//!
//!    while let Some((line_no, Ok(line))) = numbered_lines.next() {
//!        writer.send(format!("{}: {}", line_no + 1, line));
//!    }
//!}
//!```
//!
//![context]: struct.Context.html
//![headers]: ../header/struct.Headers.html
//![log]: ../log/index.html
//![body_reader]: struct.BodyReader.html

use std::collections::HashMap;
use std::io::{self, Read};
use std::net::SocketAddr;

#[cfg(feature = "rustc_json_body")]
use rustc_serialize::json;
#[cfg(feature = "rustc_json_body")]
use rustc_serialize::Decodable;

use hyper::http::h1::HttpReader;
use hyper::net::NetworkStream;
use hyper::buffer::BufReader;

#[cfg(feature = "multipart")]
use multipart::server::{HttpRequest, Multipart};

use utils;

use HttpVersion;
use Method;
use header::Headers;
use log::Log;

use Global;

///A container for handler input, like request data and utilities.
pub struct Context<'a, 'b: 'a, 's> {
    ///Headers from the HTTP request.
    pub headers: Headers,

    ///The HTTP version used in the request.
    pub http_version: HttpVersion,

    ///The client address
    pub address: SocketAddr,

    ///The HTTP method.
    pub method: Method,

    ///The requested path.
    pub path: String,

    ///Hypermedia from the current endpoint.
    pub hypermedia: Hypermedia<'s>,

    ///Route variables.
    pub variables: HashMap<String, String>,

    ///Query variables from the path.
    pub query: HashMap<String, String>,

    ///The fragment part of the URL (after #), if provided.
    pub fragment: Option<String>,

    ///Log for notes, errors and warnings.
    pub log: &'s (Log + 's),

    ///Globally accessible data.
    pub global: &'s Global,

    ///A reader for the request body.
    pub body: BodyReader<'a, 'b>,
}

///A reader for a request body.
pub struct BodyReader<'a, 'b: 'a> {
    reader: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>,

    #[cfg(feature = "multipart")]
    multipart_boundary: Option<String>
}

#[cfg(feature = "multipart")]
impl<'a, 'b> BodyReader<'a, 'b> {
    pub fn from_reader(reader: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>, headers: &Headers) -> BodyReader<'a, 'b> {
        use header::ContentType;
        use mime::{Mime, TopLevel, SubLevel, Attr, Value};

        let boundary = match headers.get() {
            Some(&ContentType(Mime(TopLevel::Multipart, SubLevel::FormData, ref attrs))) => {
                attrs.iter()
                    .find(|&&(ref attr, _)| attr == &Attr::Boundary)
                    .and_then(|&(_, ref val)| if let Value::Ext(ref boundary) = *val {
                        Some(boundary.clone())
                    } else {
                        None
                    })
            },
            _ => None
        };

        BodyReader {
            reader: reader,
            multipart_boundary: boundary
        }
    }

    pub fn as_multipart(&mut self) -> Option<Multipart<MultipartRequest>> {
        let reader = &mut self.reader;
        self.multipart_boundary.as_ref().and_then(move |boundary|
            Multipart::from_request(MultipartRequest {
                boundary: boundary,
                reader: reader
            }).ok()
        )
    }
}

#[cfg(not(feature = "multipart"))]
impl<'a, 'b> BodyReader<'a, 'b> {
    pub fn from_reader(reader: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>, _headers: &Headers) -> BodyReader<'a, 'b> {
        BodyReader {
            reader: reader
        }
    }
}

///`BodyReader` extension for reading and parsing a query string.
///
///Examples and more information can be found in [the documentation for
///`BodyReader`][body_reader].
///
///[body_reader]: struct.BodyReader.html
pub trait ExtQueryBody {
    fn read_query_body(&mut self) -> io::Result<HashMap<String, String>>;
}

impl<'a, 'b> ExtQueryBody for BodyReader<'a, 'b> {
    ///Read and parse the request body as a query string. The body will be
    ///decoded as UTF-8 and plain '+' characters will be replaced with spaces.
    ///
    ///A simplified example of how to parse `a=number&b=number`:
    ///
    ///```
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtQueryBody;
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Parse the request body as a query string
    ///    let query = context.body.read_query_body().unwrap();
    ///
    ///    //Find "a" and "b" and assume that they are numbers
    ///    let a: f64 = query.get("a").and_then(|number| number.parse().ok()).unwrap();
    ///    let b: f64 = query.get("b").and_then(|number| number.parse().ok()).unwrap();
    ///
    ///    response.send(format!("{} + {} = {}", a, b, a + b));
    ///}
    ///```
    #[inline]
    fn read_query_body(&mut self) -> io::Result<HashMap<String, String>> {
        let mut buf = Vec::new();
        try!(self.read_to_end(&mut buf));
        Ok(utils::parse_parameters(&buf))
    }
}

///`BodyReader` extension for reading and parsing a JSON body.
///
///It is available by default and can be toggled using the `rustc_json_body`
///feature. Examples and more information can be found in [the documentation
///for `BodyReader`][body_reader].
///
///[body_reader]: struct.BodyReader.html
#[cfg(feature = "rustc_json_body")]
pub trait ExtJsonBody {
    ///Read the request body into a JSON structure.
    fn read_json_body(&mut self) -> Result<json::Json, json::BuilderError>;

    ///Parse and decode the request body as some type `T`.
    fn decode_json_body<T: Decodable>(&mut self) -> json::DecodeResult<T>;
}

#[cfg(feature = "rustc_json_body")]
impl<'a, 'b> ExtJsonBody for BodyReader<'a, 'b> {
    ///Read the request body into a generic JSON structure. This structure can
    ///then be navigated and parsed freely.
    ///
    ///A simplified example of how to parse `{ "a": number, "b": number }`:
    ///
    ///```
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtJsonBody;
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Parse the request body as JSON
    ///    let json = context.body.read_json_body().unwrap();
    ///
    ///    //Find "a" and "b" in the root object and assume that they are numbers
    ///    let a = json.find("a").and_then(|number| number.as_f64()).unwrap();
    ///    let b = json.find("b").and_then(|number| number.as_f64()).unwrap();
    ///
    ///    response.send(format!("{} + {} = {}", a, b, a + b));
    ///}
    ///```
    fn read_json_body(&mut self) -> Result<json::Json, json::BuilderError> {
        json::Json::from_reader(self)
    }

    ///Read and decode a request body as a type `T`. The target type must
    ///implement `rustc_serialize::Decodable`.
    ///
    ///A simplified example of how to parse `{ "a": number, "b": number }`:
    ///
    ///```
    ///extern crate rustful;
    ///extern crate rustc_serialize;
    ///
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtJsonBody;
    ///
    ///#[derive(RustcDecodable)]
    ///struct Foo {
    ///    a: f64,
    ///    b: f64
    ///}
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Decode a JSON formatted request body into Foo
    ///    let foo: Foo = context.body.decode_json_body().unwrap();
    ///
    ///    response.send(format!("{} + {} = {}", foo.a, foo.b, foo.a + foo.b));
    ///}
    ///# fn main() {}
    ///```
    fn decode_json_body<T: Decodable>(&mut self) -> json::DecodeResult<T> {
        let mut buf = String::new();
        try!(self.read_to_string(&mut buf).map_err(|e| {
            let parse_err = json::ParserError::IoError(e);
            json::DecoderError::ParseError(parse_err)
        }));
        json::decode(&buf)
    }
}

impl<'a, 'b> Read for BodyReader<'a, 'b> {
    ///Read the request body.
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.reader.read(buf)
    }
}

///A specialized request representation for the multipart interface.
#[cfg(feature = "multipart")]
pub struct MultipartRequest<'a> {
    boundary: &'a str,
    reader: &'a mut Read
}

#[cfg(feature = "multipart")]
impl<'a> HttpRequest for MultipartRequest<'a> {
    fn is_multipart(&self) -> bool {
        true
    }

    fn boundary(&self) -> Option<&str> {
        Some(self.boundary)
    }
}

#[cfg(feature = "multipart")]
impl<'a> Read for MultipartRequest<'a> {
    ///Read the request body.
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.reader.read(buf)
    }
}

///Hypermedia connected to an API endpoint.
pub struct Hypermedia<'a> {
    ///Forward links from the current endpoint to other endpoints. These may
    ///include endpoints with the same path, but different method.
    pub links: Vec<Link<'a>>
}

impl<'a> Hypermedia<'a> {
    ///Create an empty `Hypermedia` structure.
    pub fn new() -> Hypermedia<'a> {
        Hypermedia {
            links: vec![]
        }
    }
}

///A hyperlink.
#[derive(PartialEq, Eq, Debug)]
pub struct Link<'a> {
    ///The HTTP method for which an endpoint is available. It can be left
    ///unspecified if the method doesn't matter.
    pub method: Option<Method>,
    ///A relative path from the current location.
    pub path: Vec<LinkSegment<'a>>
}

///A segment of a hyperlink path.
#[derive(PartialEq, Eq, Debug)]
pub enum LinkSegment<'a> {
    ///A static part of a path.
    Static(&'a str),
    ///A dynamic part of a path. Can be substituted with anything.
    Variable(&'a str),
    ///A recursive wildcard. Will recursively match anything.
    RecursiveWildcard
}
<commit_msg>Replace the Read trait object in MultipartContext with a concrete type<commit_after>//!Handler context and request body reading extensions.
//!
//!#Context
//!
//!The [`Context`][context] contains all the input data for the request
//!handlers, as well as some utilities. This is where request data, like
//!headers, client address and the request body can be retrieved from and it
//!can safely be picked apart, since its ownership is transferred to the
//!handler.
//!
//!##Accessing Headers
//!
//!The headers are stored in the `headers` field. See the [`Headers`][headers]
//!struct for more information about how to access them.
//!
//!```
//!use rustful::{Context, Response};
//!use rustful::header::UserAgent;
//!
//!fn my_handler(context: Context, response: Response) {
//!    if let Some(&UserAgent(ref user_agent)) = context.headers.get() {
//!        response.send(format!("got user agent string \"{}\"", user_agent));
//!    } else {
//!        response.send("no user agent string provided");
//!    }
//!}
//!```
//!
//!##Path Variables
//!
//!A router may collect variable data from paths (for example `id` in
//!`/products/:id`). The values from these variables can be accessed through
//!the `variables` field.
//!
//!```
//!use rustful::{Context, Response};
//!
//!fn my_handler(context: Context, response: Response) {
//!    if let Some(id) = context.variables.get("id") {
//!        response.send(format!("asking for product with id \"{}\"", id));
//!    } else {
//!        //This will usually not happen, unless the handler is also
//!        //assigned to a path without the `id` variable
//!        response.send("no id provided");
//!    }
//!}
//!```
//!
//!##Other URL Parts
//!
//! * Query variables (`http://example.com?a=b&c=d`) can be found in the
//!`query` field and they are accessed in exactly the same fashion as path
//!variables are used.
//!
//! * The fragment (`http://example.com#foo`) is also parsed and can be
//!accessed through `fragment` as an optional `String`.
//!
//!##Logging
//!
//!Rustful has a built in logging infrastructure and it is made available to
//!handlers through the `log` field. This provides logging and error reporting
//!in a unified and more controlled fashion than what panics and `println!`
//!gives. See the [`log`][log] module for more information about the standard
//!alternatives.
//!
//!```
//!# fn something_that_may_fail() -> Result<&'static str, &'static str> { Ok("yo") }
//!use rustful::{Context, Response};
//!use rustful::StatusCode::InternalServerError;
//!
//!fn my_handler(context: Context, mut response: Response) {
//!    match something_that_may_fail() {
//!        Ok(res) => response.send(res),
//!        Err(e) => {
//!            context.log.error(&format!("it failed! {}", e));
//!            response.set_status(InternalServerError);
//!        }
//!    }
//!}
//!```
//!
//!##Global Data
//!
//!There is also infrastructure for globally accessible data, that can be
//!accessed through the `global` field. This is meant to provide a place for
//!things like database connections or cached data that should be available to
//!all handlers. The storage space itself is immutable when the server has
//!started, so the only way to change it is through some kind of inner
//!mutability.
//!
//!```
//!use rustful::{Context, Response};
//!use rustful::StatusCode::InternalServerError;
//!
//!fn my_handler(context: Context, mut response: Response) {
//!    if let Some(some_wise_words) = context.global.get::<&str>() {
//!        response.send(format!("food for thought: {}", some_wise_words));
//!    } else {
//!        context.log.error("there should be a string literal in `global`");
//!        response.set_status(InternalServerError);
//!    }
//!}
//!```
//!
//!##Request Body
//!
//!The body will not be read in advance, unlike the other parts of the
//!request. It is instead available as a `BodyReader` in the field `body`,
//!through which it can be read and parsed as various data formats, like JSON
//!and query strings. The documentation for [`BodyReader`][body_reader] gives
//!more examples.
//!
//!```
//!use std::io::{BufReader, BufRead};
//!use rustful::{Context, Response};
//!
//!fn my_handler(context: Context, response: Response) {
//!    let mut numbered_lines = BufReader::new(context.body).lines().enumerate();
//!    let mut writer = response.into_chunked();
//!
//!    while let Some((line_no, Ok(line))) = numbered_lines.next() {
//!        writer.send(format!("{}: {}", line_no + 1, line));
//!    }
//!}
//!```
//!
//![context]: struct.Context.html
//![headers]: ../header/struct.Headers.html
//![log]: ../log/index.html
//![body_reader]: struct.BodyReader.html

use std::collections::HashMap;
use std::io::{self, Read};
use std::net::SocketAddr;

#[cfg(feature = "rustc_json_body")]
use rustc_serialize::json;
#[cfg(feature = "rustc_json_body")]
use rustc_serialize::Decodable;

use hyper::http::h1::HttpReader;
use hyper::net::NetworkStream;
use hyper::buffer::BufReader;

#[cfg(feature = "multipart")]
use multipart::server::{HttpRequest, Multipart};

use utils;

use HttpVersion;
use Method;
use header::Headers;
use log::Log;

use Global;

///A container for handler input, like request data and utilities.
pub struct Context<'a, 'b: 'a, 's> {
    ///Headers from the HTTP request.
    pub headers: Headers,

    ///The HTTP version used in the request.
    pub http_version: HttpVersion,

    ///The client address
    pub address: SocketAddr,

    ///The HTTP method.
    pub method: Method,

    ///The requested path.
    pub path: String,

    ///Hypermedia from the current endpoint.
    pub hypermedia: Hypermedia<'s>,

    ///Route variables.
    pub variables: HashMap<String, String>,

    ///Query variables from the path.
    pub query: HashMap<String, String>,

    ///The fragment part of the URL (after #), if provided.
    pub fragment: Option<String>,

    ///Log for notes, errors and warnings.
    pub log: &'s (Log + 's),

    ///Globally accessible data.
    pub global: &'s Global,

    ///A reader for the request body.
    pub body: BodyReader<'a, 'b>,
}

///A reader for a request body.
pub struct BodyReader<'a, 'b: 'a> {
    reader: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>,

    #[cfg(feature = "multipart")]
    multipart_boundary: Option<String>
}

#[cfg(feature = "multipart")]
impl<'a, 'b> BodyReader<'a, 'b> {
    pub fn from_reader(reader: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>, headers: &Headers) -> BodyReader<'a, 'b> {
        use header::ContentType;
        use mime::{Mime, TopLevel, SubLevel, Attr, Value};

        let boundary = match headers.get() {
            Some(&ContentType(Mime(TopLevel::Multipart, SubLevel::FormData, ref attrs))) => {
                attrs.iter()
                    .find(|&&(ref attr, _)| attr == &Attr::Boundary)
                    .and_then(|&(_, ref val)| if let Value::Ext(ref boundary) = *val {
                        Some(boundary.clone())
                    } else {
                        None
                    })
            },
            _ => None
        };

        BodyReader {
            reader: reader,
            multipart_boundary: boundary
        }
    }

    pub fn as_multipart<'r>(&'r mut self) -> Option<Multipart<MultipartRequest<'r, 'a, 'b>>> {
        let reader = &mut self.reader;
        self.multipart_boundary.as_ref().and_then(move |boundary|
            Multipart::from_request(MultipartRequest {
                boundary: boundary,
                reader: reader
            }).ok()
        )
    }
}

#[cfg(not(feature = "multipart"))]
impl<'a, 'b> BodyReader<'a, 'b> {
    pub fn from_reader(reader: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>, _headers: &Headers) -> BodyReader<'a, 'b> {
        BodyReader {
            reader: reader
        }
    }
}

///`BodyReader` extension for reading and parsing a query string.
///
///Examples and more information can be found in [the documentation for
///`BodyReader`][body_reader].
///
///[body_reader]: struct.BodyReader.html
pub trait ExtQueryBody {
    fn read_query_body(&mut self) -> io::Result<HashMap<String, String>>;
}

impl<'a, 'b> ExtQueryBody for BodyReader<'a, 'b> {
    ///Read and parse the request body as a query string. The body will be
    ///decoded as UTF-8 and plain '+' characters will be replaced with spaces.
    ///
    ///A simplified example of how to parse `a=number&b=number`:
    ///
    ///```
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtQueryBody;
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Parse the request body as a query string
    ///    let query = context.body.read_query_body().unwrap();
    ///
    ///    //Find "a" and "b" and assume that they are numbers
    ///    let a: f64 = query.get("a").and_then(|number| number.parse().ok()).unwrap();
    ///    let b: f64 = query.get("b").and_then(|number| number.parse().ok()).unwrap();
    ///
    ///    response.send(format!("{} + {} = {}", a, b, a + b));
    ///}
    ///```
    #[inline]
    fn read_query_body(&mut self) -> io::Result<HashMap<String, String>> {
        let mut buf = Vec::new();
        try!(self.read_to_end(&mut buf));
        Ok(utils::parse_parameters(&buf))
    }
}

///`BodyReader` extension for reading and parsing a JSON body.
///
///It is available by default and can be toggled using the `rustc_json_body`
///feature. Examples and more information can be found in [the documentation
///for `BodyReader`][body_reader].
///
///[body_reader]: struct.BodyReader.html
#[cfg(feature = "rustc_json_body")]
pub trait ExtJsonBody {
    ///Read the request body into a JSON structure.
    fn read_json_body(&mut self) -> Result<json::Json, json::BuilderError>;

    ///Parse and decode the request body as some type `T`.
    fn decode_json_body<T: Decodable>(&mut self) -> json::DecodeResult<T>;
}

#[cfg(feature = "rustc_json_body")]
impl<'a, 'b> ExtJsonBody for BodyReader<'a, 'b> {
    ///Read the request body into a generic JSON structure. This structure can
    ///then be navigated and parsed freely.
    ///
    ///A simplified example of how to parse `{ "a": number, "b": number }`:
    ///
    ///```
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtJsonBody;
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Parse the request body as JSON
    ///    let json = context.body.read_json_body().unwrap();
    ///
    ///    //Find "a" and "b" in the root object and assume that they are numbers
    ///    let a = json.find("a").and_then(|number| number.as_f64()).unwrap();
    ///    let b = json.find("b").and_then(|number| number.as_f64()).unwrap();
    ///
    ///    response.send(format!("{} + {} = {}", a, b, a + b));
    ///}
    ///```
    fn read_json_body(&mut self) -> Result<json::Json, json::BuilderError> {
        json::Json::from_reader(self)
    }

    ///Read and decode a request body as a type `T`. The target type must
    ///implement `rustc_serialize::Decodable`.
    ///
    ///A simplified example of how to parse `{ "a": number, "b": number }`:
    ///
    ///```
    ///extern crate rustful;
    ///extern crate rustc_serialize;
    ///
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtJsonBody;
    ///
    ///#[derive(RustcDecodable)]
    ///struct Foo {
    ///    a: f64,
    ///    b: f64
    ///}
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Decode a JSON formatted request body into Foo
    ///    let foo: Foo = context.body.decode_json_body().unwrap();
    ///
    ///    response.send(format!("{} + {} = {}", foo.a, foo.b, foo.a + foo.b));
    ///}
    ///# fn main() {}
    ///```
    fn decode_json_body<T: Decodable>(&mut self) -> json::DecodeResult<T> {
        let mut buf = String::new();
        try!(self.read_to_string(&mut buf).map_err(|e| {
            let parse_err = json::ParserError::IoError(e);
            json::DecoderError::ParseError(parse_err)
        }));
        json::decode(&buf)
    }
}

impl<'a, 'b> Read for BodyReader<'a, 'b> {
    ///Read the request body.
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.reader.read(buf)
    }
}

///A specialized request representation for the multipart interface.
#[cfg(feature = "multipart")]
pub struct MultipartRequest<'r, 'a: 'r, 'b: 'a> {
    boundary: &'r str,
    reader: &'r mut HttpReader<&'a mut BufReader<&'b mut NetworkStream>>
}

#[cfg(feature = "multipart")]
impl<'r, 'a, 'b> HttpRequest for MultipartRequest<'r, 'a, 'b> {
    fn is_multipart(&self) -> bool {
        true
    }

    fn boundary(&self) -> Option<&str> {
        Some(self.boundary)
    }
}

#[cfg(feature = "multipart")]
impl<'r, 'a, 'b> Read for MultipartRequest<'r, 'a, 'b> {
    ///Read the request body.
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.reader.read(buf)
    }
}

///Hypermedia connected to an API endpoint.
pub struct Hypermedia<'a> {
    ///Forward links from the current endpoint to other endpoints. These may
    ///include endpoints with the same path, but different method.
    pub links: Vec<Link<'a>>
}

impl<'a> Hypermedia<'a> {
    ///Create an empty `Hypermedia` structure.
    pub fn new() -> Hypermedia<'a> {
        Hypermedia {
            links: vec![]
        }
    }
}

///A hyperlink.
#[derive(PartialEq, Eq, Debug)]
pub struct Link<'a> {
    ///The HTTP method for which an endpoint is available. It can be left
    ///unspecified if the method doesn't matter.
    pub method: Option<Method>,
    ///A relative path from the current location.
    pub path: Vec<LinkSegment<'a>>
}

///A segment of a hyperlink path.
#[derive(PartialEq, Eq, Debug)]
pub enum LinkSegment<'a> {
    ///A static part of a path.
    Static(&'a str),
    ///A dynamic part of a path. Can be substituted with anything.
    Variable(&'a str),
    ///A recursive wildcard. Will recursively match anything.
    RecursiveWildcard
}
<|endoftext|>


<commit_before>use ffi;
use libc::{c_uint, c_int, c_void};
use num::complex::Complex64;

use plan::RawPlan;

/// How much effort FFTW should put into computing the best strategy
/// to use.
///
/// The `FFTW_WISDOM_ONLY` rigor level is replaced by the
pub enum Rigor {
    Estimate,
    Measure,
    Patient,
    Exhaustive,
}
impl Rigor {
    fn flags(self) -> c_uint {
        match self {
            Estimate => ffi::FFTW_ESTIMATE,
            Measure => ffi::FFTW_MEASURE,
            Patient => ffi::FFTW_PATIENT,
            Exhaustive => ffi::FFTW_EXHAUSTIVE,
        }
    }
}

/// The direction of the transform to perform..
pub enum Direction {
    Forward, Backward
}

/// Control the basic properties of a set of transforms.
pub struct Planner {
    rigor: Rigor,
    wisdom_restriction: bool,
    direction: Direction,
}

impl Planner {
    /// Construct a new planner with default values.
    ///
    /// This defaults to a forward transform with estimate rigor.
    pub fn new() -> Planner {
        Planner {
            rigor: Estimate,
            wisdom_restriction: false,
            direction: Forward,
        }
    }

    /// Set the rigor to use for this plan.
    pub fn rigor(&mut self, r: Rigor) -> &mut Planner {
        self.rigor = r;
        self
    }
    /// Set whether the planner should only be successfully created if
    /// there exists wisdom created with at least the rigor level set.
    pub fn wisdom_restriction(&mut self, wisdom_only: bool) -> &mut Planner {
        self.wisdom_restriction = wisdom_only;
        self
    }

    /// Set the direction of the transform to perform.
    pub fn direction(&mut self, direction: Direction) -> &mut Planner {
        self.direction = direction;
        self
    }

    fn flags(&self) -> c_uint {
        self.rigor.flags() | if self.wisdom_restriction {
            ffi::FFTW_WISDOM_ONLY
        } else {
            0
        }
    }
    fn dir(&self) -> c_int {
        match self.direction {
            Forward => ffi::FFTW_FORWARD,
            Backward => ffi::FFTW_BACKWARD,
        }
    }

    pub fn c2c<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[Complex64]>, O: DerefMut<[Complex64]>
    {
        assert!(in_.len() <= out.len());
        PlanMem {
            plan: *self,
            n: in_.len() as c_int,
            in_: in_,
            out: Some(out),
            planner: c2c,
        }
    }
    pub fn c2r<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[Complex64]>, O: DerefMut<[f64]>
    {
        assert!(in_.len() <= out.len() / 2 + 1);
        PlanMem {
            plan: *self,
            n: 2 * (in_.len() as c_int - 1),
            in_: in_,
            out: Some(out),
            planner: c2r,
        }
    }
    pub fn r2c<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[f64]>, O: DerefMut<[Complex64]>
    {
        assert!(in_.len() / 2 + 1 <= out.len());
        PlanMem {
            plan: *self,
            n: in_.len() as c_int,
            in_: in_,
            out: Some(out),
            planner: r2c,
        }
    }
    #[cfg(r2r_is_hard)]
    pub fn r2r<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[f64]>, O: DerefMut<[f64]>
    {
        assert!(in_.len() <= out.len());
        PlanMem {
            plan: *self,
            n: in_.len() as c_int,
            in_: in_,
            out: Some(out),
            planner: r2r,
        }
    }
}

unsafe fn c2c(n: c_int, in_: *mut c_void, out: *mut c_void,
              sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_dft_1d(n,
                          in_ as *mut ffi::fftw_complex, out as *mut ffi::fftw_complex,
                          sign, flags)
}
unsafe fn r2c(n: c_int, in_: *mut c_void, out: *mut c_void,
              _sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_dft_r2c_1d(n,
                              in_ as *mut f64, out as *mut ffi::fftw_complex,
                              flags)
}
unsafe fn c2r(n: c_int, in_: *mut c_void, out: *mut c_void,
              _sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_dft_c2r_1d(n,
                              in_ as *mut ffi::fftw_complex, out as *mut f64,
                              flags)
}
#[cfg(r2r_is_hard)]
unsafe fn r2r(n: c_int, in_: *mut c_void, out: *mut c_void,
              sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_r2r_1d(n,
                          in_ as *mut f64, out as *mut f64,
                          sign, flags)
}

pub struct PlanMem<I, O> {
    plan: Planner,
    n: c_int,
    in_: I,
    out: Option<O>,
    planner: unsafe fn(c_int, *mut c_void, *mut c_void, c_int, c_uint) -> ffi::fftw_plan,
}

impl<X, Y, I: DerefMut<[X]>, O: DerefMut<[Y]>> PlanMem<I, O> {
    pub fn plan(mut self) -> Result<Planned<I, O>, PlanMem<I, O>> {
        let in_ptr = self.in_.as_mut_ptr() as *mut c_void;
        let out_ptr = match self.out {
            None => in_ptr,
            Some(ref mut o) => o.as_mut_ptr() as *mut c_void,
        };

        let plan = RawPlan::new(|| unsafe {
            (self.planner)(self.n,
                           in_ptr,
                           out_ptr,
                           self.plan.dir(),
                           self.plan.flags())
        });

        match plan {
            None => Err(self),
            Some(p) => Ok(Planned { mem: self, plan: p })
        }
    }
}

pub struct Planned<I, O> {
    mem: PlanMem<I, O>,
    plan: RawPlan,
}

impl<X, Y, I: DerefMut<[X]>, O: DerefMut<[Y]>> Planned<I, O> {
    pub fn input(&mut self) -> &mut [X] {
        &mut *self.mem.in_
    }
    pub fn output(&mut self) -> Option<&mut [Y]> {
        self.mem.out.as_mut().map(|o| &mut **o)
    }

    pub fn execute(&mut self) {
        unsafe {
            self.plan.execute()
        }
    }
}
<commit_msg>Add inplace c2c support.<commit_after>use ffi;
use libc::{c_uint, c_int, c_void};
use num::complex::Complex64;

use plan::RawPlan;

/// How much effort FFTW should put into computing the best strategy
/// to use.
///
/// The `FFTW_WISDOM_ONLY` rigor level is replaced by the
pub enum Rigor {
    Estimate,
    Measure,
    Patient,
    Exhaustive,
}
impl Rigor {
    fn flags(self) -> c_uint {
        match self {
            Estimate => ffi::FFTW_ESTIMATE,
            Measure => ffi::FFTW_MEASURE,
            Patient => ffi::FFTW_PATIENT,
            Exhaustive => ffi::FFTW_EXHAUSTIVE,
        }
    }
}

/// The direction of the transform to perform..
pub enum Direction {
    Forward, Backward
}

/// Control the basic properties of a set of transforms.
pub struct Planner {
    rigor: Rigor,
    wisdom_restriction: bool,
    direction: Direction,
}

impl Planner {
    /// Construct a new planner with default values.
    ///
    /// This defaults to a forward transform with estimate rigor.
    pub fn new() -> Planner {
        Planner {
            rigor: Estimate,
            wisdom_restriction: false,
            direction: Forward,
        }
    }

    /// Set the rigor to use for this plan.
    pub fn rigor(&mut self, r: Rigor) -> &mut Planner {
        self.rigor = r;
        self
    }
    /// Set whether the planner should only be successfully created if
    /// there exists wisdom created with at least the rigor level set.
    pub fn wisdom_restriction(&mut self, wisdom_only: bool) -> &mut Planner {
        self.wisdom_restriction = wisdom_only;
        self
    }

    /// Set the direction of the transform to perform.
    pub fn direction(&mut self, direction: Direction) -> &mut Planner {
        self.direction = direction;
        self
    }

    fn flags(&self) -> c_uint {
        self.rigor.flags() | if self.wisdom_restriction {
            ffi::FFTW_WISDOM_ONLY
        } else {
            0
        }
    }
    fn dir(&self) -> c_int {
        match self.direction {
            Forward => ffi::FFTW_FORWARD,
            Backward => ffi::FFTW_BACKWARD,
        }
    }

    pub fn inplace(&self) -> InPlacePlanner {
        InPlacePlanner { plan: *self }
    }

    pub fn c2c<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[Complex64]>, O: DerefMut<[Complex64]>
    {
        assert!(in_.len() <= out.len());
        PlanMem {
            plan: *self,
            n: in_.len() as c_int,
            in_: in_,
            out: Some(out),
            planner: c2c,
        }
    }
    pub fn c2r<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[Complex64]>, O: DerefMut<[f64]>
    {
        assert!(in_.len() <= out.len() / 2 + 1);
        PlanMem {
            plan: *self,
            n: 2 * (in_.len() as c_int - 1),
            in_: in_,
            out: Some(out),
            planner: c2r,
        }
    }
    pub fn r2c<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[f64]>, O: DerefMut<[Complex64]>
    {
        assert!(in_.len() / 2 + 1 <= out.len());
        PlanMem {
            plan: *self,
            n: in_.len() as c_int,
            in_: in_,
            out: Some(out),
            planner: r2c,
        }
    }
    #[cfg(r2r_is_hard)]
    pub fn r2r<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[f64]>, O: DerefMut<[f64]>
    {
        assert!(in_.len() <= out.len());
        PlanMem {
            plan: *self,
            n: in_.len() as c_int,
            in_: in_,
            out: Some(out),
            planner: r2r,
        }
    }
}

pub struct InPlacePlanner {
    plan: Planner
}

impl InPlacePlanner {
    pub fn c2c<I>(&self, in_: I) -> PlanMem<I, I>
        where I: DerefMut<[Complex64]>
    {
        assert!(in_.len() <= 0xFF_FF_FF_FF);
        PlanMem {
            plan: self.plan,
            n: in_.len() as c_int,
            in_: in_,
            out: None,
            planner: c2c,
        }
    }
}

unsafe fn c2c(n: c_int, in_: *mut c_void, out: *mut c_void,
              sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_dft_1d(n,
                          in_ as *mut ffi::fftw_complex, out as *mut ffi::fftw_complex,
                          sign, flags)
}
unsafe fn r2c(n: c_int, in_: *mut c_void, out: *mut c_void,
              _sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_dft_r2c_1d(n,
                              in_ as *mut f64, out as *mut ffi::fftw_complex,
                              flags)
}
unsafe fn c2r(n: c_int, in_: *mut c_void, out: *mut c_void,
              _sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_dft_c2r_1d(n,
                              in_ as *mut ffi::fftw_complex, out as *mut f64,
                              flags)
}
#[cfg(r2r_is_hard)]
unsafe fn r2r(n: c_int, in_: *mut c_void, out: *mut c_void,
              sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_r2r_1d(n,
                          in_ as *mut f64, out as *mut f64,
                          sign, flags)
}

pub struct PlanMem<I, O> {
    plan: Planner,
    n: c_int,
    in_: I,
    out: Option<O>,
    planner: unsafe fn(c_int, *mut c_void, *mut c_void, c_int, c_uint) -> ffi::fftw_plan,
}

impl<X, Y, I: DerefMut<[X]>, O: DerefMut<[Y]>> PlanMem<I, O> {
    pub fn plan(mut self) -> Result<Planned<I, O>, PlanMem<I, O>> {
        let in_ptr = self.in_.as_mut_ptr() as *mut c_void;
        let out_ptr = match self.out {
            None => in_ptr,
            Some(ref mut o) => o.as_mut_ptr() as *mut c_void,
        };

        let plan = RawPlan::new(|| unsafe {
            (self.planner)(self.n,
                           in_ptr,
                           out_ptr,
                           self.plan.dir(),
                           self.plan.flags())
        });

        match plan {
            None => Err(self),
            Some(p) => Ok(Planned { mem: self, plan: p })
        }
    }
}

pub struct Planned<I, O> {
    mem: PlanMem<I, O>,
    plan: RawPlan,
}

impl<X, Y, I: DerefMut<[X]>, O: DerefMut<[Y]>> Planned<I, O> {
    pub fn input(&mut self) -> &mut [X] {
        &mut *self.mem.in_
    }
    pub fn output(&mut self) -> Option<&mut [Y]> {
        self.mem.out.as_mut().map(|o| &mut **o)
    }

    pub fn execute(&mut self) {
        unsafe {
            self.plan.execute()
        }
    }
}
<|endoftext|>