<commit_before>extern crate regex;

extern crate rusoto_core;
extern crate rusoto_sts;
extern crate rusoto_dynamodb;

pub mod SessionHandler {
    use std::fs::{File, OpenOptions};
    use std::io::BufReader;
    use std::io;
    use std::io::prelude::*;
    use std::io::{stdin, stdout};
    use std::env;
    use rusoto_core::{ProfileProvider, Region, default_tls_client};
    use rusoto_sts::{Sts, StsClient, GetSessionTokenRequest, GetSessionTokenResponse, GetSessionTokenError, Credentials};
    use std::collections::HashMap;

    struct AWSConfig {
        profiles: HashMap<String, AWSProfile>,
    }

    #[derive(Debug)]
    struct AWSProfile {
        source_profile: Option<String>,
        region: Option<String>,
        output: Option<String>,
        role_arn: Option<String>,
        mfa_serial: Option<String>,
        ot_session_name: Option<String>,
        ot_expiration: Option<String>,
        ot_source_profile: Option<String>,
        ot_role_arn: Option<String>,
    }

    impl AWSConfig {
        fn save(&self) -> Result<(), io::Error> {
            println!("Saving config to disk");
            let mut bluenine_config_path = env::home_dir().unwrap().display().to_string();
            bluenine_config_path.push_str("/.aws/config");
            let mut file = OpenOptions::new()
                        .write(true)
                        .truncate(true)
                        .open(bluenine_config_path)
                        .unwrap();

            let mut prof = String::new();
            for (name, profile) in &self.profiles {
                prof.push_str(&format!("[profile {}]\n", name));

                let source_profile = &profile.source_profile;
                match source_profile {
                    &Some(ref source_profile) => {
                        prof.push_str(&format!("source_profile = {}\n", source_profile));
                    },
                    &None => {},
                };

                let region = &profile.region;
                match region {
                    &Some(ref region) => {
                        prof.push_str(&format!("region = {}\n", region));
                    },
                    &None => {},
                };

                let output = &profile.output;
                match output {
                    &Some(ref output) => {
                        prof.push_str(&format!("output = {}\n", output));
                    },
                    &None => {},
                };

                let role_arn = &profile.role_arn;
                match role_arn {
                    &Some(ref role_arn) => {
                        prof.push_str(&format!("role_arn = {}\n", role_arn));
                    },
                    &None => {},
                };

                let mfa_serial = &profile.mfa_serial;
                match mfa_serial {
                    &Some(ref mfa_serial) => {
                        prof.push_str(&format!("mfa_serial = {}\n", mfa_serial));
                    },
                    &None => {},
                };

                let ot_session_name = &profile.ot_session_name;
                match ot_session_name {
                    &Some(ref ot_session_name) => {
                        prof.push_str(&format!("ot_session_name = {}\n", ot_session_name));
                    },
                    &None => {},
                };

                let ot_expiration = &profile.ot_expiration;
                match ot_expiration {
                    &Some(ref ot_expiration) => {
                        prof.push_str(&format!("ot_expiration = {}\n", ot_expiration));
                    },
                    &None => {},
                };

                let ot_expiration = &profile.ot_expiration;
                match ot_expiration {
                    &Some(ref ot_expiration) => {
                        prof.push_str(&format!("ot_expiration = {}\n", ot_expiration));
                    },
                    &None => {},
                };

                let ot_source_profile = &profile.ot_source_profile;
                match ot_source_profile {
                    &Some(ref ot_source_profile) => {
                        prof.push_str(&format!("ot_source_profile = {}\n", ot_source_profile));
                    },
                    &None => {},
                };

                let ot_role_arn = &profile.ot_role_arn;
                match ot_role_arn {
                    &Some(ref ot_role_arn) => {
                        prof.push_str(&format!("ot_role_arn = {}\n", ot_role_arn));
                    },
                    &None => {},
                };

                prof.push_str("\n");
            }

            try!(file.write_all(prof.as_bytes()));
            Ok(())
        }

        fn get_profile(&self, name: &str) -> &AWSProfile {
            if (&self.profiles).contains_key(name) {
                &self.profiles[name]
            }
            else {
                panic!("Could not find profile {}", name);
            }
        }

        fn contains_profile(&self, name: &str) -> bool {
            if (&self.profiles).contains_key(name) {
                true
            }
            else {
                false
            }
        }
    }

    pub fn create(profile_name: &str) {
        println!("Loading config file");
        let aws_config = load_config();

        let mut session_name = profile_name.clone().to_string();
        session_name.push_str("-session");
        if aws_config.contains_profile(&session_name) {
            println!("Session {} for profile {} already exists", session_name, profile_name);
        }

        println!("Creating session for profile \"{}\"...", profile_name);
        let aws_profile = aws_config.get_profile(profile_name);

        let mut provider = ProfileProvider::new().unwrap();
        provider.set_profile(profile_name);
        // let region = &aws_profile.region;
        // match region {
        //     &Some(ref region) => region,
        //     &None => panic!("You must specify a region for profile {}", profile_name)
        // };
        // println!("Region: {:?}", region.as_ref().unwrap());
        let client = StsClient::new(default_tls_client().unwrap(), provider, Region::EuWest1);

        let mfa_serial = &aws_profile.mfa_serial;
        if mfa_serial.is_some() {
            print!("Enter AWS MFA code for profile [{}]: ", profile_name);
            stdout().flush();
            let mut token_code = String::new();
            stdin().read_line(&mut token_code)
                .ok()
                .expect("Couldn't read line");
            token_code.pop(); // Remove newline

            let request = GetSessionTokenRequest {
                duration_seconds: None,
                serial_number: Some(mfa_serial.as_ref().unwrap().to_owned()),
                token_code: Some(token_code),
            };
            let response = client.get_session_token(&request);
            match response {
                Ok(response) => {
                    match save_profile(profile_name, &aws_profile) {
                        Ok(_) => println!("Saved profile to config file."),
                        Err(err) => println!("Error saving profile config to file: {:?}", err)
                    };
                    let credentials = response.credentials.unwrap();
                    match save_credentials(profile_name, credentials) {
                        Ok(_) => println!("Saved to credentials file."),
                        Err(err) => println!("Error saving credentials to file: {:?}", err)
                    };
                },
                Err(err) => panic!("Failed to get session token for profile {}: {:?}", profile_name, err),
            };
        }
    }
    pub fn show(profile_name: &str) {
        println!("Showing config for profile {}...", profile_name);
    }

    pub fn refresh() {
        println!("Refreshing sessions...");
    }

    pub fn clean(profile_name: &str) {
        println!("Loading config file");
        let mut aws_config = load_config();
        let mut session_name = profile_name.clone().to_string();
        session_name.push_str("-session");

        if aws_config.contains_profile(&session_name) {
            println!("Cleaning session {}", session_name);
            aws_config.profiles.remove(&session_name);
            aws_config.save();
            // Remove credentials also
            remove_credentials(&session_name);
        }
        else {
            println!("No profiles to clean");
        }
    }

    fn load_config() -> AWSConfig {
        let aws_config_file = read_aws_config_file();
        let profiles = split_config_file(aws_config_file);

        // Create an instance of the AWSConfig struct
        let mut aws_config = AWSConfig {
            profiles: HashMap::new()
        };

        // Iterate over profile chunks
        for profile in profiles {
            // Create a vector of string that holds each line
            let split = profile.split("\n");
            let lines: Vec<String> = split.map(|s| s.to_string()).collect();

            // Get the profile name from the first line
            let profile_line = lines[0].to_owned();

            // Lets ignore the default for now
            if profile_line == "[default]" {
                continue;
            }

            let split2 = profile_line.split(" ");
            let mut words: Vec<String> = split2.map(|s| s.to_string()).collect();
            let mut profile_name = String::new();
            if words.len() > 1 {
                words[1].pop();
                profile_name = words[1].trim_right().to_owned();
            }

            let mut aws_profile = AWSProfile{
                source_profile: None,
                region: None,
                output: None,
                role_arn: None,
                mfa_serial: None,
                ot_expiration: None,
                ot_session_name: None,
                ot_source_profile: None,
                ot_role_arn: None,
            };

            for i in 1..lines.len() {
                let split = lines[i].split(" = ");
                let config: Vec<String> = split.map(|s| s.to_string()).collect();
                let key = &config[0];
                let value = config[1].to_owned();
                match key.as_ref() {
                    "mfa_serial" => aws_profile.mfa_serial = Some(value),
                    "output" => aws_profile.output = Some(value),
                    "region" => aws_profile.region = Some(value),
                    "role_arn" => aws_profile.role_arn = Some(value),
                    "source_profile" => aws_profile.source_profile = Some(value),
                    "ot_session_name" => aws_profile.ot_session_name = Some(value),
                    "ot_expiration" => aws_profile.ot_expiration = Some(value),
                    "ot_source_profile" => aws_profile.ot_source_profile = Some(value),
                    "ot_role_arn" => aws_profile.ot_role_arn = Some(value),
                    _ => (),
                }
            }

            if profile_name != "" {
                aws_config.profiles.insert(profile_name.clone(), aws_profile);
            }
        }

        aws_config
    }

    fn read_aws_config_file() -> String {
        let path = match env::home_dir() {
            Some(path) => path,
            None => panic!("Could not retrieve user's home directory."),
        };
        let config_file_path = format!("{}/.aws/config", path.display());

        let f = File::open(config_file_path).expect("Could not find AWS config file.");
        let mut buf_reader = BufReader::new(f);
        let mut contents = String::new();
        buf_reader.read_to_string(&mut contents).expect("Found config file but could not read it.");

        contents
    }

    fn read_aws_credentials_file() -> String {
        let path = match env::home_dir() {
            Some(path) => path,
            None => panic!("Could not retrieve user's home directory."),
        };
        let config_file_path = format!("{}/.aws/credentials", path.display());

        let f = File::open(config_file_path).expect("Could not find AWS credentials file.");
        let mut buf_reader = BufReader::new(f);
        let mut contents = String::new();
        buf_reader.read_to_string(&mut contents).expect("Found credentials file but could not read it.");

        contents
    }

    fn split_config_file(aws_config: String) -> Vec<String> {
        let split = aws_config.split("\n\n");
        let mut profiles: Vec<String> = split.map(|s| s.to_string()).collect();;

        profiles.pop(); // Remove last element as it is always empty
        profiles
    }

    fn save_credentials(profile_name: &str, credentials: Credentials) -> Result<(), io::Error> {
        let mut aws_credentials_path = env::home_dir().unwrap().display().to_string();
        aws_credentials_path.push_str("/.aws/credentials");
        let mut file = OpenOptions::new()
                       .write(true)
                       .append(true)
                       .open(aws_credentials_path)
                       .unwrap();

        let mut creds = String::new();
        creds.push_str(&format!("[{}-session]\n", profile_name));
        creds.push_str(&format!("aws_access_key_id = {}\n", credentials.access_key_id));
        creds.push_str(&format!("expiration = {}\n", credentials.expiration));
        creds.push_str(&format!("aws_secret_access_key = {}\n", credentials.secret_access_key));
        creds.push_str(&format!("aws_session_token = {}\n\n", credentials.session_token));
        try!(file.write_all(creds.as_bytes()));
        Ok(())
    }

    fn remove_credentials(profile_name: &str) -> Result<(), io::Error> {
        println!("Saving credentials to disk");
        let aws_credentials_file = read_aws_credentials_file();
        let credentials = split_config_file(aws_credentials_file);
        let mut aws_credentials_path = env::home_dir().unwrap().display().to_string();
        aws_credentials_path.push_str("/.aws/credentials");
        let mut file = OpenOptions::new()
                .write(true)
                .truncate(true)
                .open(aws_credentials_path)
                .unwrap();

        let mut creds = String::new();
        for credential in credentials {
            let split = credential.split("\n");
            let lines: Vec<String> = split.map(|s| s.to_string()).collect();

            // Get the profile name from the first line
            let profile_line = lines[0].to_owned();
            if profile_line == format!("[{}]", profile_name) {
                continue;
            }
            creds.push_str(&credential);
            creds.push_str("\n\n");
        }
        try!(file.write_all(creds.as_bytes()));
        Ok(())
    }

    fn save_profile(profile_name: &str, aws_profile: &AWSProfile) -> Result<(), io::Error> {
        let mut aws_config_path = env::home_dir().unwrap().display().to_string();
        aws_config_path.push_str("/.aws/config");
        let mut file = OpenOptions::new()
                       .write(true)
                       .append(true)
                       .open(aws_config_path)
                       .unwrap();

        let region = &aws_profile.region;
        match region {
            &Some(ref region) => {
                let mut prof = String::new();
                prof.push_str(&format!("[profile {}-session]\n", profile_name));
                prof.push_str(&format!("region = {}\n\n", region));
                try!(file.write_all(prof.as_bytes()));
                Ok(())
            },
            &None => {
                let region = "us-east-1";
                let mut prof = String::new();
                prof.push_str(&format!("[profile {}-session]\n", profile_name));
                prof.push_str(&format!("region = {}\n\n", region));
                try!(file.write_all(prof.as_bytes()));
                Ok(())
            },
        }
    }
}
<commit_msg>Add parent and child logic<commit_after>extern crate regex;

extern crate rusoto_core;
extern crate rusoto_sts;
extern crate rusoto_dynamodb;

pub mod SessionHandler {
    use std::fs::{File, OpenOptions};
    use std::io::BufReader;
    use std::io;
    use std::io::prelude::*;
    use std::io::{stdin, stdout};
    use std::env;
    use rusoto_core::{ProfileProvider, Region, default_tls_client};
    use rusoto_sts::{Sts, StsClient, GetSessionTokenRequest, GetSessionTokenResponse,
        GetSessionTokenError, AssumeRoleRequest, AssumeRoleResponse, AssumeRoleError, Credentials};

    use std::collections::HashMap;

    struct AWSConfig {
        profiles: HashMap<String, AWSProfile>,
    }

    #[derive(Debug)]
    struct AWSProfile {
        source_profile: Option<String>,
        region: Option<String>,
        output: Option<String>,
        role_arn: Option<String>,
        mfa_serial: Option<String>,
        ot_session_name: Option<String>,
        ot_expiration: Option<String>,
        ot_source_profile: Option<String>,
        ot_role_arn: Option<String>,
    }

    impl AWSConfig {
        fn save(&self) -> Result<(), io::Error> {
            println!("Saving config to disk");
            let mut bluenine_config_path = env::home_dir().unwrap().display().to_string();
            bluenine_config_path.push_str("/.aws/config");
            let mut file = OpenOptions::new()
                        .write(true)
                        .truncate(true)
                        .open(bluenine_config_path)
                        .unwrap();

            let mut prof = String::new();
            for (name, profile) in &self.profiles {
                prof.push_str(&format!("[profile {}]\n", name));

                let source_profile = &profile.source_profile;
                match source_profile {
                    &Some(ref source_profile) => {
                        prof.push_str(&format!("source_profile = {}\n", source_profile));
                    },
                    &None => {},
                };

                let region = &profile.region;
                match region {
                    &Some(ref region) => {
                        prof.push_str(&format!("region = {}\n", region));
                    },
                    &None => {},
                };

                let output = &profile.output;
                match output {
                    &Some(ref output) => {
                        prof.push_str(&format!("output = {}\n", output));
                    },
                    &None => {},
                };

                let role_arn = &profile.role_arn;
                match role_arn {
                    &Some(ref role_arn) => {
                        prof.push_str(&format!("role_arn = {}\n", role_arn));
                    },
                    &None => {},
                };

                let mfa_serial = &profile.mfa_serial;
                match mfa_serial {
                    &Some(ref mfa_serial) => {
                        prof.push_str(&format!("mfa_serial = {}\n", mfa_serial));
                    },
                    &None => {},
                };

                let ot_session_name = &profile.ot_session_name;
                match ot_session_name {
                    &Some(ref ot_session_name) => {
                        prof.push_str(&format!("ot_session_name = {}\n", ot_session_name));
                    },
                    &None => {},
                };

                let ot_expiration = &profile.ot_expiration;
                match ot_expiration {
                    &Some(ref ot_expiration) => {
                        prof.push_str(&format!("ot_expiration = {}\n", ot_expiration));
                    },
                    &None => {},
                };

                let ot_expiration = &profile.ot_expiration;
                match ot_expiration {
                    &Some(ref ot_expiration) => {
                        prof.push_str(&format!("ot_expiration = {}\n", ot_expiration));
                    },
                    &None => {},
                };

                let ot_source_profile = &profile.ot_source_profile;
                match ot_source_profile {
                    &Some(ref ot_source_profile) => {
                        prof.push_str(&format!("ot_source_profile = {}\n", ot_source_profile));
                    },
                    &None => {},
                };

                let ot_role_arn = &profile.ot_role_arn;
                match ot_role_arn {
                    &Some(ref ot_role_arn) => {
                        prof.push_str(&format!("ot_role_arn = {}\n", ot_role_arn));
                    },
                    &None => {},
                };

                prof.push_str("\n");
            }

            try!(file.write_all(prof.as_bytes()));
            Ok(())
        }

        fn get_profile(&self, name: &str) -> &AWSProfile {
            if (&self.profiles).contains_key(name) {
                &self.profiles[name]
            }
            else {
                panic!("Could not find profile {}", name);
            }
        }

        fn contains_profile(&self, name: &str) -> bool {
            if (&self.profiles).contains_key(name) {
                true
            }
            else {
                false
            }
        }
    }

    pub fn create(profile_name: &str) {
        println!("Loading config file");
        let aws_config = load_config();

        let mut session_name = profile_name.clone().to_string();
        session_name.push_str("-session");
        if aws_config.contains_profile(&session_name) {
            println!("Session {} for profile {} already exists", session_name, profile_name);
        }

        println!("Creating session for profile \"{}\"...", profile_name);
        let aws_profile = aws_config.get_profile(profile_name);

        // Check if this is a child profile
        let source_profile = &aws_profile.source_profile;
        match source_profile {
            &Some(ref source_profile) => {
                println!("This is a child profile");
                let mut session_name = source_profile.clone().to_string();
                session_name.push_str("-session");
                if aws_config.contains_profile(&session_name) {
                    println!("Session {} for profile {} already exists", session_name, source_profile);
                    let mut provider = ProfileProvider::new().unwrap();
                    provider.set_profile(session_name);
                    let client = StsClient::new(default_tls_client().unwrap(), provider, Region::EuWest1);

                    let mut role_arn = &aws_profile.role_arn;
                    let role_arn_string = role_arn.as_ref().unwrap();
                    let v: Vec<&str> = role_arn_string.split('/').collect();

                    let request = AssumeRoleRequest {
                        duration_seconds: None,
                        external_id: None,
                        policy: None,
                        role_arn: role_arn_string.to_owned(),
                        role_session_name: v[1].to_owned(),
                        serial_number: None,
                        token_code: None,
                    };
                    let response = client.assume_role(&request);
                    match response {
                        Ok(response) => {
                            match save_profile(profile_name, &aws_profile) {
                                Ok(_) => println!("Saved profile to config file."),
                                Err(err) => println!("Error saving profile config to file: {:?}", err)
                            };
                            let credentials = response.credentials.unwrap();
                            match save_credentials(profile_name, credentials) {
                                Ok(_) => println!("Saved to credentials file."),
                                Err(err) => println!("Error saving credentials to file: {:?}", err)
                            };
                        },
                        Err(err) => panic!("Failed to get session token for profile {}: {:?}", profile_name, err),
                    };
                }
                else {
                    println!("Parent profile does not exist. Will have to create it");
                    return;
                }
            },
            &None => {
                let mut provider = ProfileProvider::new().unwrap();
                provider.set_profile(profile_name);
                let client = StsClient::new(default_tls_client().unwrap(), provider, Region::EuWest1);

                let mfa_serial = &aws_profile.mfa_serial;
                if mfa_serial.is_some() {
                    print!("Enter AWS MFA code for profile [{}]: ", profile_name);
                    stdout().flush();
                    let mut token_code = String::new();
                    stdin().read_line(&mut token_code)
                        .ok()
                        .expect("Couldn't read line");
                    token_code.pop(); // Remove newline

                    let request = GetSessionTokenRequest {
                        duration_seconds: None,
                        serial_number: Some(mfa_serial.as_ref().unwrap().to_owned()),
                        token_code: Some(token_code),
                    };
                    let response = client.get_session_token(&request);
                    match response {
                        Ok(response) => {
                            match save_profile(profile_name, &aws_profile) {
                                Ok(_) => println!("Saved profile to config file."),
                                Err(err) => println!("Error saving profile config to file: {:?}", err)
                            };
                            let credentials = response.credentials.unwrap();
                            match save_credentials(profile_name, credentials) {
                                Ok(_) => println!("Saved to credentials file."),
                                Err(err) => println!("Error saving credentials to file: {:?}", err)
                            };
                        },
                        Err(err) => panic!("Failed to get session token for profile {}: {:?}", profile_name, err),
                    };
                }
            },
        };
    }
    pub fn show(profile_name: &str) {
        println!("Showing config for profile {}...", profile_name);
    }

    pub fn refresh() {
        println!("Refreshing sessions...");
    }

    pub fn clean(profile_name: &str) {
        println!("Loading config file");
        let mut aws_config = load_config();
        let mut session_name = profile_name.clone().to_string();
        session_name.push_str("-session");

        if aws_config.contains_profile(&session_name) {
            println!("Cleaning session {}", session_name);
            aws_config.profiles.remove(&session_name);
            aws_config.save();
            // Remove credentials also
            remove_credentials(&session_name);
        }
        else {
            println!("No profiles to clean");
        }
    }

    fn load_config() -> AWSConfig {
        let aws_config_file = read_aws_config_file();
        let profiles = split_config_file(aws_config_file);

        // Create an instance of the AWSConfig struct
        let mut aws_config = AWSConfig {
            profiles: HashMap::new()
        };

        // Iterate over profile chunks
        for profile in profiles {
            // Create a vector of string that holds each line
            let split = profile.split("\n");
            let lines: Vec<String> = split.map(|s| s.to_string()).collect();

            // Get the profile name from the first line
            let profile_line = lines[0].to_owned();

            // Lets ignore the default for now
            if profile_line == "[default]" {
                continue;
            }

            let split2 = profile_line.split(" ");
            let mut words: Vec<String> = split2.map(|s| s.to_string()).collect();
            let mut profile_name = String::new();
            if words.len() > 1 {
                words[1].pop();
                profile_name = words[1].trim_right().to_owned();
            }

            let mut aws_profile = AWSProfile{
                source_profile: None,
                region: None,
                output: None,
                role_arn: None,
                mfa_serial: None,
                ot_expiration: None,
                ot_session_name: None,
                ot_source_profile: None,
                ot_role_arn: None,
            };

            for i in 1..lines.len() {
                let split = lines[i].split(" = ");
                let config: Vec<String> = split.map(|s| s.to_string()).collect();
                let key = &config[0];
                let value = config[1].to_owned();
                match key.as_ref() {
                    "mfa_serial" => aws_profile.mfa_serial = Some(value),
                    "output" => aws_profile.output = Some(value),
                    "region" => aws_profile.region = Some(value),
                    "role_arn" => aws_profile.role_arn = Some(value),
                    "source_profile" => aws_profile.source_profile = Some(value),
                    "ot_session_name" => aws_profile.ot_session_name = Some(value),
                    "ot_expiration" => aws_profile.ot_expiration = Some(value),
                    "ot_source_profile" => aws_profile.ot_source_profile = Some(value),
                    "ot_role_arn" => aws_profile.ot_role_arn = Some(value),
                    _ => (),
                }
            }

            if profile_name != "" {
                aws_config.profiles.insert(profile_name.clone(), aws_profile);
            }
        }

        aws_config
    }

    fn read_aws_config_file() -> String {
        let path = match env::home_dir() {
            Some(path) => path,
            None => panic!("Could not retrieve user's home directory."),
        };
        let config_file_path = format!("{}/.aws/config", path.display());

        let f = File::open(config_file_path).expect("Could not find AWS config file.");
        let mut buf_reader = BufReader::new(f);
        let mut contents = String::new();
        buf_reader.read_to_string(&mut contents).expect("Found config file but could not read it.");

        contents
    }

    fn read_aws_credentials_file() -> String {
        let path = match env::home_dir() {
            Some(path) => path,
            None => panic!("Could not retrieve user's home directory."),
        };
        let config_file_path = format!("{}/.aws/credentials", path.display());

        let f = File::open(config_file_path).expect("Could not find AWS credentials file.");
        let mut buf_reader = BufReader::new(f);
        let mut contents = String::new();
        buf_reader.read_to_string(&mut contents).expect("Found credentials file but could not read it.");

        contents
    }

    fn split_config_file(aws_config: String) -> Vec<String> {
        let split = aws_config.split("\n\n");
        let mut profiles: Vec<String> = split.map(|s| s.to_string()).collect();;

        profiles.pop(); // Remove last element as it is always empty
        profiles
    }

    fn save_credentials(profile_name: &str, credentials: Credentials) -> Result<(), io::Error> {
        let mut aws_credentials_path = env::home_dir().unwrap().display().to_string();
        aws_credentials_path.push_str("/.aws/credentials");
        let mut file = OpenOptions::new()
                       .write(true)
                       .append(true)
                       .open(aws_credentials_path)
                       .unwrap();

        let mut creds = String::new();
        creds.push_str(&format!("[{}-session]\n", profile_name));
        creds.push_str(&format!("aws_access_key_id = {}\n", credentials.access_key_id));
        creds.push_str(&format!("expiration = {}\n", credentials.expiration));
        creds.push_str(&format!("aws_secret_access_key = {}\n", credentials.secret_access_key));
        creds.push_str(&format!("aws_session_token = {}\n\n", credentials.session_token));
        try!(file.write_all(creds.as_bytes()));
        Ok(())
    }

    fn remove_credentials(profile_name: &str) -> Result<(), io::Error> {
        println!("Saving credentials to disk");
        let aws_credentials_file = read_aws_credentials_file();
        let credentials = split_config_file(aws_credentials_file);
        let mut aws_credentials_path = env::home_dir().unwrap().display().to_string();
        aws_credentials_path.push_str("/.aws/credentials");
        let mut file = OpenOptions::new()
                .write(true)
                .truncate(true)
                .open(aws_credentials_path)
                .unwrap();

        let mut creds = String::new();
        for credential in credentials {
            let split = credential.split("\n");
            let lines: Vec<String> = split.map(|s| s.to_string()).collect();

            // Get the profile name from the first line
            let profile_line = lines[0].to_owned();
            if profile_line == format!("[{}]", profile_name) {
                continue;
            }
            creds.push_str(&credential);
            creds.push_str("\n\n");
        }
        try!(file.write_all(creds.as_bytes()));
        Ok(())
    }

    fn save_profile(profile_name: &str, aws_profile: &AWSProfile) -> Result<(), io::Error> {
        let mut aws_config_path = env::home_dir().unwrap().display().to_string();
        aws_config_path.push_str("/.aws/config");
        let mut file = OpenOptions::new()
                       .write(true)
                       .append(true)
                       .open(aws_config_path)
                       .unwrap();

        let region = &aws_profile.region;
        match region {
            &Some(ref region) => {
                let mut prof = String::new();
                prof.push_str(&format!("[profile {}-session]\n", profile_name));
                prof.push_str(&format!("region = {}\n\n", region));
                try!(file.write_all(prof.as_bytes()));
                Ok(())
            },
            &None => {
                let region = "us-east-1";
                let mut prof = String::new();
                prof.push_str(&format!("[profile {}-session]\n", profile_name));
                prof.push_str(&format!("region = {}\n\n", region));
                try!(file.write_all(prof.as_bytes()));
                Ok(())
            },
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code, bad_style)]

pub const ENOMEM: i32 = 12;

include!(concat!(env!("OUT_DIR"), "/celix_bind.rs"));
include!(concat!(env!("OUT_DIR"), "/constants.rs"));<commit_msg>Added constant to temporarily fix missing values<commit_after>#![allow(dead_code, bad_style)]

pub const ENOMEM: i32 = 12;
pub const celix_thread_default : (i32,i32) = (0,0);

include!(concat!(env!("OUT_DIR"), "/celix_bind.rs"));
include!(concat!(env!("OUT_DIR"), "/constants.rs"));

// macros for functions needed by celix
<|endoftext|>


<commit_before>//! A simple library for parsing an XML file into an in-memory tree structure
//!
//! Not recommended for large XML files, as it will load the entire file into memory.
//!
//! # Example
//!
//! ```no_run
//! use xmltree::Element;
//! use std::fs::File;
//!
//! let data: &'static str = r##"
//! <?xml version="1.0" encoding="utf-8" standalone="yes"?>
//! <names>
//!     <name first="bob" last="jones" />
//!     <name first="elizabeth" last="smith" />
//! </names>
//! "##;
//!
//! let mut names_element = Element::parse(data.as_bytes()).unwrap();
//!
//! println!("{:#?}", names_element);
//! {
//!     // get first `name` element
//!     let name = names_element.get_mut_child("name").expect("Can't find name element");
//!     name.attributes.insert("suffix".to_owned(), "mr".to_owned());
//! }
//! names_element.write(File::create("result.xml").unwrap());
//!
//!
//! ```
extern crate xml;

use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt;
use std::io::{Read, Write};

pub use xml::namespace::Namespace;
use xml::reader::{EventReader, XmlEvent};
pub use xml::writer::{EmitterConfig, Error};

/// Represents an XML element.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Element {
    /// This elements prefix, if any
    pub prefix: Option<String>,

    /// This elements namespace, if any
    pub namespace: Option<String>,

    /// The full list of namespaces, if any
    ///
    /// The `Namespace` type is exported from the `xml-rs` crate.
    pub namespaces: Option<Namespace>,

    /// The name of the Element.  Does not include any namespace info
    pub name: String,

    /// The Element attributes
    pub attributes: HashMap<String, String>,

    /// Children
    pub children: Vec<Element>,

    /// The text data for this element
    pub text: Option<String>,
}

/// Errors that can occur parsing XML
#[derive(Debug)]
pub enum ParseError {
    /// The XML is invalid
    MalformedXml(xml::reader::Error),
    /// This library is unable to process this XML. This can occur if, for
    /// example, the XML contains processing instructions.
    CannotParse,
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ParseError::MalformedXml(ref e) => write!(f, "Malformed XML. {}", e),
            ParseError::CannotParse => write!(f, "Cannot parse"),
        }
    }
}

impl std::error::Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::MalformedXml(..) => "Malformed XML",
            ParseError::CannotParse => "Cannot parse",
        }
    }

    fn cause(&self) -> Option<&dyn std::error::Error> {
        match *self {
            ParseError::MalformedXml(ref e) => Some(e),
            ParseError::CannotParse => None,
        }
    }
}

fn build<B: Read>(reader: &mut EventReader<B>, mut elem: Element) -> Result<Element, ParseError> {
    loop {
        match reader.next() {
            Ok(XmlEvent::EndElement { ref name }) => {
                if name.local_name == elem.name {
                    return Ok(elem);
                } else {
                    return Err(ParseError::CannotParse);
                }
            }
            Ok(XmlEvent::StartElement {
                name,
                attributes,
                namespace,
            }) => {
                let mut attr_map = HashMap::new();
                for attr in attributes {
                    attr_map.insert(attr.name.local_name, attr.value);
                }

                let new_elem = Element {
                    prefix: name.prefix,
                    namespace: name.namespace,
                    namespaces: if namespace.is_essentially_empty() {
                        None
                    } else {
                        Some(namespace)
                    },
                    name: name.local_name,
                    attributes: attr_map,
                    children: Vec::new(),
                    text: None,
                };
                elem.children.push(build(reader, new_elem)?);
            }
            Ok(XmlEvent::Characters(s)) => {
                elem.text = Some(s);
            }
            Ok(XmlEvent::Whitespace(..)) | Ok(XmlEvent::Comment(..)) => (),
            Ok(XmlEvent::CData(s)) => elem.text = Some(s),
            Ok(XmlEvent::StartDocument { .. })
            | Ok(XmlEvent::EndDocument)
            | Ok(XmlEvent::ProcessingInstruction { .. }) => return Err(ParseError::CannotParse),
            Err(e) => return Err(ParseError::MalformedXml(e)),
        }
    }
}

impl Element {
    /// Create a new empty element with given name
    ///
    /// All other fields are empty
    pub fn new(name: &str) -> Element {
        Element {
            name: String::from(name),
            prefix: None,
            namespace: None,
            namespaces: None,
            attributes: HashMap::new(),
            children: Vec::new(),
            text: None,
        }
    }

    /// Parses some data into an Element
    pub fn parse<R: Read>(r: R) -> Result<Element, ParseError> {
        let mut reader = EventReader::new(r);
        loop {
            match reader.next() {
                Ok(XmlEvent::StartElement {
                    name,
                    attributes,
                    namespace,
                }) => {
                    let mut attr_map = HashMap::new();
                    for attr in attributes {
                        attr_map.insert(attr.name.local_name, attr.value);
                    }

                    let root = Element {
                        prefix: name.prefix,
                        namespace: name.namespace,
                        namespaces: if namespace.is_essentially_empty() {
                            None
                        } else {
                            Some(namespace)
                        },
                        name: name.local_name,
                        attributes: attr_map,
                        children: Vec::new(),
                        text: None,
                    };
                    return build(&mut reader, root);
                }
                Ok(XmlEvent::Comment(..))
                | Ok(XmlEvent::Whitespace(..))
                | Ok(XmlEvent::StartDocument { .. }) => continue,
                Ok(XmlEvent::EndDocument)
                | Ok(XmlEvent::EndElement { .. })
                | Ok(XmlEvent::Characters(..))
                | Ok(XmlEvent::CData(..))
                | Ok(XmlEvent::ProcessingInstruction { .. }) => {
                    return Err(ParseError::CannotParse)
                }
                Err(e) => return Err(ParseError::MalformedXml(e)),
            }
        }
    }

    fn _write<B: Write>(&self, emitter: &mut xml::writer::EventWriter<B>) -> Result<(), Error> {
        use xml::attribute::Attribute;
        use xml::name::Name;
        use xml::writer::events::XmlEvent;

        let mut name = Name::local(&self.name);
        if let Some(ref ns) = self.namespace {
            name.namespace = Some(ns);
        }
        if let Some(ref p) = self.prefix {
            name.prefix = Some(p);
        }

        let mut attributes = Vec::with_capacity(self.attributes.len());
        for (k, v) in &self.attributes {
            attributes.push(Attribute {
                name: Name::local(k),
                value: v,
            });
        }

        let empty_ns = Namespace::empty();
        let namespace = if let Some(ref ns) = self.namespaces {
            Cow::Borrowed(ns)
        } else {
            Cow::Borrowed(&empty_ns)
        };

        emitter.write(XmlEvent::StartElement {
            name,
            attributes: Cow::Owned(attributes),
            namespace,
        })?;
        if let Some(ref t) = self.text {
            emitter.write(XmlEvent::Characters(t))?;
        }
        for elem in &self.children {
            elem._write(emitter)?;
        }
        emitter.write(XmlEvent::EndElement { name: Some(name) })?;

        Ok(())
    }

    /// Writes out this element as the root element in an new XML document
    pub fn write<W: Write>(&self, w: W) -> Result<(), Error> {
        self.write_with_config(w, EmitterConfig::new())
    }

    /// Writes out this element as the root element in a new XML document using the provided configuration
    pub fn write_with_config<W: Write>(&self, w: W, config: EmitterConfig) -> Result<(), Error> {
        use xml::common::XmlVersion;
        use xml::writer::events::XmlEvent;
        use xml::writer::EventWriter;

        let mut emitter = EventWriter::new_with_config(w, config);
        emitter.write(XmlEvent::StartDocument {
            version: XmlVersion::Version10,
            encoding: None,
            standalone: None,
        })?;
        self._write(&mut emitter)
    }

    /// Find a child element with the given name and return a reference to it.
    pub fn get_child<P: ElementPredicate>(&self, k: P) -> Option<&Element> {
        self.children.iter().find(|e| k.match_element(e))
    }

    /// Find a child element with the given name and return a mutable reference to it.
    pub fn get_mut_child<P: ElementPredicate>(&mut self, k: P) -> Option<&mut Element> {
        self.children.iter_mut().find(|e| k.match_element(e))
    }

    /// Find a child element with the given name, remove and return it.
    pub fn take_child<P: ElementPredicate>(&mut self, k: P) -> Option<Element> {
        self.children
            .iter()
            .position(|e| k.match_element(e))
            .map(|i| self.children.remove(i))
    }
}

/// A predicate for matching elements.
///
/// The default implementations allow you to match by tag name or a tuple of
/// tag name and namespace.
pub trait ElementPredicate {
    fn match_element(&self, e: &Element) -> bool;
}

// Unfortunately,
// `impl<TN> ElementPredicate for TN where String: PartialEq<TN>` and
// `impl<TN, NS> ElementPredicate for (TN, NS) where String: PartialEq<TN>, String: PartialEq<NS>`
// are conflicting implementations, even though we know that there is no
// implementation for tuples. We just manually implement `ElementPredicate` for
// all `PartialEq` impls of `String` and forward them to the 1-tuple version.
//
// This can probably be fixed once specialization is stable.
impl<TN> ElementPredicate for (TN,)
where
    String: PartialEq<TN>,
{
    fn match_element(&self, e: &Element) -> bool {
        e.name == self.0
    }
}

impl<'a> ElementPredicate for &'a str {
    fn match_element(&self, e: &Element) -> bool {
        (*self,).match_element(e)
    }
}

impl<'a> ElementPredicate for Cow<'a, str> {
    fn match_element(&self, e: &Element) -> bool {
        (&**self,).match_element(e)
    }
}

impl ElementPredicate for String {
    fn match_element(&self, e: &Element) -> bool {
        (&**self,).match_element(e)
    }
}

impl<TN, NS> ElementPredicate for (TN, NS)
where
    String: PartialEq<TN>,
    String: PartialEq<NS>,
{
    fn match_element(&self, e: &Element) -> bool {
        e.name == self.0
            && e.namespace
                .as_ref()
                .map(|ns| ns == &self.1)
                .unwrap_or(false)
    }
}
<commit_msg>Small doc update<commit_after>//! A simple library for parsing an XML file into an in-memory tree structure
//!
//! Not recommended for large XML files, as it will load the entire file into memory.
//!
//! # Example
//!
//! ```no_run
//! use xmltree::Element;
//! use std::fs::File;
//!
//! let data: &'static str = r##"
//! <?xml version="1.0" encoding="utf-8" standalone="yes"?>
//! <names>
//!     <name first="bob" last="jones" />
//!     <name first="elizabeth" last="smith" />
//! </names>
//! "##;
//!
//! let mut names_element = Element::parse(data.as_bytes()).unwrap();
//!
//! println!("{:#?}", names_element);
//! {
//!     // get first `name` element
//!     let name = names_element.get_mut_child("name").expect("Can't find name element");
//!     name.attributes.insert("suffix".to_owned(), "mr".to_owned());
//! }
//! names_element.write(File::create("result.xml").unwrap());
//!
//!
//! ```
extern crate xml;

use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt;
use std::io::{Read, Write};

pub use xml::namespace::Namespace;
use xml::reader::{EventReader, XmlEvent};
pub use xml::writer::{EmitterConfig, Error};

/// Represents an XML element.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Element {
    /// This elements prefix, if any
    pub prefix: Option<String>,

    /// This elements namespace, if any
    pub namespace: Option<String>,

    /// The full list of namespaces, if any
    ///
    /// The `Namespace` type is exported from the `xml-rs` crate.
    pub namespaces: Option<Namespace>,

    /// The name of the Element.  Does not include any namespace info
    pub name: String,

    /// The Element attributes
    pub attributes: HashMap<String, String>,

    /// Children
    pub children: Vec<Element>,

    /// The text data for this element
    pub text: Option<String>,
}

/// Errors that can occur parsing XML
#[derive(Debug)]
pub enum ParseError {
    /// The XML is invalid
    MalformedXml(xml::reader::Error),
    /// This library is unable to process this XML. This can occur if, for
    /// example, the XML contains processing instructions.
    CannotParse,
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ParseError::MalformedXml(ref e) => write!(f, "Malformed XML. {}", e),
            ParseError::CannotParse => write!(f, "Cannot parse"),
        }
    }
}

impl std::error::Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::MalformedXml(..) => "Malformed XML",
            ParseError::CannotParse => "Cannot parse",
        }
    }

    fn cause(&self) -> Option<&dyn std::error::Error> {
        match *self {
            ParseError::MalformedXml(ref e) => Some(e),
            ParseError::CannotParse => None,
        }
    }
}

fn build<B: Read>(reader: &mut EventReader<B>, mut elem: Element) -> Result<Element, ParseError> {
    loop {
        match reader.next() {
            Ok(XmlEvent::EndElement { ref name }) => {
                if name.local_name == elem.name {
                    return Ok(elem);
                } else {
                    return Err(ParseError::CannotParse);
                }
            }
            Ok(XmlEvent::StartElement {
                name,
                attributes,
                namespace,
            }) => {
                let mut attr_map = HashMap::new();
                for attr in attributes {
                    attr_map.insert(attr.name.local_name, attr.value);
                }

                let new_elem = Element {
                    prefix: name.prefix,
                    namespace: name.namespace,
                    namespaces: if namespace.is_essentially_empty() {
                        None
                    } else {
                        Some(namespace)
                    },
                    name: name.local_name,
                    attributes: attr_map,
                    children: Vec::new(),
                    text: None,
                };
                elem.children.push(build(reader, new_elem)?);
            }
            Ok(XmlEvent::Characters(s)) => {
                elem.text = Some(s);
            }
            Ok(XmlEvent::Whitespace(..)) | Ok(XmlEvent::Comment(..)) => (),
            Ok(XmlEvent::CData(s)) => elem.text = Some(s),
            Ok(XmlEvent::StartDocument { .. })
            | Ok(XmlEvent::EndDocument)
            | Ok(XmlEvent::ProcessingInstruction { .. }) => return Err(ParseError::CannotParse),
            Err(e) => return Err(ParseError::MalformedXml(e)),
        }
    }
}

impl Element {
    /// Create a new empty element with given name
    ///
    /// All other fields are empty
    pub fn new(name: &str) -> Element {
        Element {
            name: String::from(name),
            prefix: None,
            namespace: None,
            namespaces: None,
            attributes: HashMap::new(),
            children: Vec::new(),
            text: None,
        }
    }

    /// Parses some data into an Element
    pub fn parse<R: Read>(r: R) -> Result<Element, ParseError> {
        let mut reader = EventReader::new(r);
        loop {
            match reader.next() {
                Ok(XmlEvent::StartElement {
                    name,
                    attributes,
                    namespace,
                }) => {
                    let mut attr_map = HashMap::new();
                    for attr in attributes {
                        attr_map.insert(attr.name.local_name, attr.value);
                    }

                    let root = Element {
                        prefix: name.prefix,
                        namespace: name.namespace,
                        namespaces: if namespace.is_essentially_empty() {
                            None
                        } else {
                            Some(namespace)
                        },
                        name: name.local_name,
                        attributes: attr_map,
                        children: Vec::new(),
                        text: None,
                    };
                    return build(&mut reader, root);
                }
                Ok(XmlEvent::Comment(..))
                | Ok(XmlEvent::Whitespace(..))
                | Ok(XmlEvent::StartDocument { .. }) => continue,
                Ok(XmlEvent::EndDocument)
                | Ok(XmlEvent::EndElement { .. })
                | Ok(XmlEvent::Characters(..))
                | Ok(XmlEvent::CData(..))
                | Ok(XmlEvent::ProcessingInstruction { .. }) => {
                    return Err(ParseError::CannotParse)
                }
                Err(e) => return Err(ParseError::MalformedXml(e)),
            }
        }
    }

    fn _write<B: Write>(&self, emitter: &mut xml::writer::EventWriter<B>) -> Result<(), Error> {
        use xml::attribute::Attribute;
        use xml::name::Name;
        use xml::writer::events::XmlEvent;

        let mut name = Name::local(&self.name);
        if let Some(ref ns) = self.namespace {
            name.namespace = Some(ns);
        }
        if let Some(ref p) = self.prefix {
            name.prefix = Some(p);
        }

        let mut attributes = Vec::with_capacity(self.attributes.len());
        for (k, v) in &self.attributes {
            attributes.push(Attribute {
                name: Name::local(k),
                value: v,
            });
        }

        let empty_ns = Namespace::empty();
        let namespace = if let Some(ref ns) = self.namespaces {
            Cow::Borrowed(ns)
        } else {
            Cow::Borrowed(&empty_ns)
        };

        emitter.write(XmlEvent::StartElement {
            name,
            attributes: Cow::Owned(attributes),
            namespace,
        })?;
        if let Some(ref t) = self.text {
            emitter.write(XmlEvent::Characters(t))?;
        }
        for elem in &self.children {
            elem._write(emitter)?;
        }
        emitter.write(XmlEvent::EndElement { name: Some(name) })?;

        Ok(())
    }

    /// Writes out this element as the root element in an new XML document
    pub fn write<W: Write>(&self, w: W) -> Result<(), Error> {
        self.write_with_config(w, EmitterConfig::new())
    }

    /// Writes out this element as the root element in a new XML document using the provided configuration
    pub fn write_with_config<W: Write>(&self, w: W, config: EmitterConfig) -> Result<(), Error> {
        use xml::common::XmlVersion;
        use xml::writer::events::XmlEvent;
        use xml::writer::EventWriter;

        let mut emitter = EventWriter::new_with_config(w, config);
        emitter.write(XmlEvent::StartDocument {
            version: XmlVersion::Version10,
            encoding: None,
            standalone: None,
        })?;
        self._write(&mut emitter)
    }

    /// Find a child element with the given name and return a reference to it.
    pub fn get_child<P: ElementPredicate>(&self, k: P) -> Option<&Element> {
        self.children.iter().find(|e| k.match_element(e))
    }

    /// Find a child element with the given name and return a mutable reference to it.
    pub fn get_mut_child<P: ElementPredicate>(&mut self, k: P) -> Option<&mut Element> {
        self.children.iter_mut().find(|e| k.match_element(e))
    }

    /// Find a child element with the given name, remove and return it.
    pub fn take_child<P: ElementPredicate>(&mut self, k: P) -> Option<Element> {
        self.children
            .iter()
            .position(|e| k.match_element(e))
            .map(|i| self.children.remove(i))
    }
}

/// A predicate for matching elements.
///
/// The default implementations allow you to match by tag name or a tuple of
/// tag name and namespace.
pub trait ElementPredicate {
    fn match_element(&self, e: &Element) -> bool;
}

// Unfortunately,
// `impl<TN> ElementPredicate for TN where String: PartialEq<TN>` and
// `impl<TN, NS> ElementPredicate for (TN, NS) where String: PartialEq<TN>, String: PartialEq<NS>`
// are conflicting implementations, even though we know that there is no
// implementation for tuples. We just manually implement `ElementPredicate` for
// all `PartialEq` impls of `String` and forward them to the 1-tuple version.
//
// This can probably be fixed once specialization is stable.
impl<TN> ElementPredicate for (TN,)
where
    String: PartialEq<TN>,
{
    fn match_element(&self, e: &Element) -> bool {
        e.name == self.0
    }
}

impl<'a> ElementPredicate for &'a str {
    /// Search by tag name
    fn match_element(&self, e: &Element) -> bool {
        (*self,).match_element(e)
    }
}

impl<'a> ElementPredicate for Cow<'a, str> {
    /// Search by tag name
    fn match_element(&self, e: &Element) -> bool {
        (&**self,).match_element(e)
    }
}

impl ElementPredicate for String {
    /// Search by tag name
    fn match_element(&self, e: &Element) -> bool {
        (&**self,).match_element(e)
    }
}

impl<TN, NS> ElementPredicate for (TN, NS)
where
    String: PartialEq<TN>,
    String: PartialEq<NS>,
{
    /// Search by a tuple of (tagname, namespace)
    fn match_element(&self, e: &Element) -> bool {
        e.name == self.0
            && e.namespace
                .as_ref()
                .map(|ns| ns == &self.1)
                .unwrap_or(false)
    }
}
<|endoftext|>


<commit_before>use std::iter::Peekable;
use std::vec::IntoIter;
use std::collections::HashMap;

#[derive(Debug,PartialEq,Clone)]
pub enum Token {
    Number(String),
    String(String),
    Name(String),
    ParenOpening,
    ParenClosing,
}

pub fn tokenizer(input: &str) -> Result<Vec<Token>, String> {
    let mut tokens: Vec<Token> = vec![];

    let mut char_iter = input.chars().peekable();
    while let Some(c) = char_iter.next() {
        match c {
            c if c.is_whitespace() => continue,
            '(' => tokens.push(Token::ParenOpening),
            ')' => tokens.push(Token::ParenClosing),
            '0'...'9' => {
                let mut value = String::new();
                value.push(c);

                while let Some(&'0'...'9') = char_iter.peek() {
                    value.push(char_iter.next().unwrap());
                }

                tokens.push(Token::Number(value));
            }
            'a'...'z' => {
                let mut value = String::new();
                value.push(c);

                while let Some(&'a'...'z') = char_iter.peek() {
                    value.push(char_iter.next().unwrap());
                }

                tokens.push(Token::Name(value));
            }
            '"' => {
                let mut value = String::new();
                // ignore opening "

                while match char_iter.peek() {
                          Some(&'"') | None => false,
                          _ => true,
                      } {
                    value.push(char_iter.next().unwrap());
                }
                tokens.push(Token::String(value));

                // skip closing ""
                char_iter.next().unwrap();
            }
            _ => return Err(format!("I don't know what this character is: {}", c)),
        }
    }

    Ok(tokens)
}

#[derive(Debug,PartialEq,Eq,Hash)]
pub enum NodeType {
    Program,
    CallExpression,
    StringLiteral,
    NumberLiteral,
}

#[derive(Debug,PartialEq,Clone)]
pub enum Node {
    Program { body: Vec<Node> },
    CallExpression { name: String, params: Vec<Node> },
    StringLiteral(String),
    NumberLiteral(String),
}

impl Node {
    fn get_type(&self) -> NodeType {
        match *self {
            Node::Program { .. } => NodeType::Program,
            Node::CallExpression { .. } => NodeType::CallExpression,
            Node::StringLiteral(_) => NodeType::StringLiteral,
            Node::NumberLiteral(_) => NodeType::NumberLiteral,
        }
    }
}

pub fn parser(tokens: Vec<Token>) -> Result<Node, String> {
    fn walk(token: Token, token_iter: &mut Peekable<IntoIter<Token>>) -> Result<Node, String> {
        match token {
            Token::Number(value) => Ok(Node::NumberLiteral(value)),
            Token::String(value) => Ok(Node::StringLiteral(value)),
            Token::ParenOpening => {
                if let Some(token) = token_iter.next() {
                    match token {
                        Token::Name(name) => {
                            let mut params: Vec<Node> = vec![];

                            while match token_iter.peek() {
                                      Some(&Token::ParenClosing) |
                                      None => false,
                                      _ => true,
                                  } {
                                match walk(token_iter.next().unwrap(), token_iter) {
                                    Ok(nodes) => params.push(nodes),
                                    Err(value) => return Err(value),
                                }
                            }

                            // skip Token::ParenClosing
                            token_iter.next().unwrap();

                            Ok(Node::CallExpression {
                                   name: name,
                                   params: params,
                               })
                        }
                        _ => {
                            return Err(format!("{:?} isn't followed by a {:?}.",
                                               Token::ParenOpening,
                                               Token::Name("example".to_string())))
                        }
                    }
                } else {
                    return Err(format!("{:?} isn't followed by a node.", Token::ParenOpening));
                }
            }
            _ => {
                return Err(format!("I don't know what this token is or this is a token which \
                                    should be covered elsewhere: {:?}",
                                   token))
            }
        }
    }

    let mut body: Vec<Node> = vec![];

    let mut token_iter = tokens.into_iter().peekable();
    while let Some(token) = token_iter.next() {
        match walk(token, &mut token_iter) {
            Ok(nodes) => body.push(nodes),
            Err(value) => return Err(value),
        }
    }

    Ok(Node::Program { body: body })
}

pub struct Visitor {
    pub enter: Option<Box<Fn(&Node, Option<&Node>)>>,
    pub exit: Option<Box<Fn(&Node, Option<&Node>)>>,
}

pub fn traverser(ast: Node, visitors: HashMap<NodeType, Visitor>) {
    fn traverse_nodes(nodes: &Vec<Node>,
                      parent: Option<&Node>,
                      visitors: &HashMap<NodeType, Visitor>) {
        for node in nodes {
            traverse_node(&node, parent, visitors);
        }
    };

    fn traverse_node(node: &Node, parent: Option<&Node>, visitors: &HashMap<NodeType, Visitor>) {
        let visitor = visitors.get(&node.get_type());

        if visitor.is_some() {
            if let Some(ref enter) = visitor.unwrap().enter {
                enter(&node, parent);
            }
        }

        match *node {
            Node::Program { ref body } => traverse_nodes(body, Some(node), visitors),
            Node::CallExpression { ref params, .. } => traverse_nodes(params, Some(node), visitors),
            _ => {}
            //_ => println!("We can't have an unknown node here!"),
        }

        if visitor.is_some() {
            if let Some(ref exit) = visitor.unwrap().exit {
                exit(&node, parent);
            }
        }
    };

    traverse_node(&ast, None, &visitors);
}

// pub struct NodeWithContext<'a> {
//     node: Node,
//     context: &'a Vec<TransformedNode>,
// }

#[derive(Debug,PartialEq,Clone)]
pub enum Callee {
    Identifier(String),
}

#[derive(Debug,PartialEq,Clone)]
pub enum TransformedNode {
    Program { body: Vec<TransformedNode> },
    ExpressionStatement { expression: Box<TransformedNode> },
    CallExpression {
        callee: Callee,
        arguments: Vec<TransformedNode>,
    },
    StringLiteral(String),
    NumberLiteral(String),
}

pub fn transformer(ast: Node) -> TransformedNode {
    let context: Vec<TransformedNode> = vec![];

    {
        // let ast_with_context = NodeWithContext {
        //     node: &ast,
        //     context: &context,
        // };

        let mut visitors = HashMap::new();
        visitors.insert(NodeType::Program,
                    Visitor {
                        enter: Some(Box::new(|node: &Node, parent: Option<&Node>| {
                            println!("test enter works!")
                        })),
                        exit: None,
                    });

        traverser(ast, visitors);
    }

    TransformedNode::Program { body: context }
}
<commit_msg>non working traverser<commit_after>use std::iter::Peekable;
use std::vec::IntoIter;
use std::collections::HashMap;

#[derive(Debug,PartialEq,Clone)]
pub enum Token {
    Number(String),
    String(String),
    Name(String),
    ParenOpening,
    ParenClosing,
}

pub fn tokenizer(input: &str) -> Result<Vec<Token>, String> {
    let mut tokens: Vec<Token> = vec![];

    let mut char_iter = input.chars().peekable();
    while let Some(c) = char_iter.next() {
        match c {
            c if c.is_whitespace() => continue,
            '(' => tokens.push(Token::ParenOpening),
            ')' => tokens.push(Token::ParenClosing),
            '0'...'9' => {
                let mut value = String::new();
                value.push(c);

                while let Some(&'0'...'9') = char_iter.peek() {
                    value.push(char_iter.next().unwrap());
                }

                tokens.push(Token::Number(value));
            }
            'a'...'z' => {
                let mut value = String::new();
                value.push(c);

                while let Some(&'a'...'z') = char_iter.peek() {
                    value.push(char_iter.next().unwrap());
                }

                tokens.push(Token::Name(value));
            }
            '"' => {
                let mut value = String::new();
                // ignore opening "

                while match char_iter.peek() {
                          Some(&'"') | None => false,
                          _ => true,
                      } {
                    value.push(char_iter.next().unwrap());
                }
                tokens.push(Token::String(value));

                // skip closing ""
                char_iter.next().unwrap();
            }
            _ => return Err(format!("I don't know what this character is: {}", c)),
        }
    }

    Ok(tokens)
}

#[derive(Debug,PartialEq,Eq,Hash)]
pub enum NodeType {
    Program,
    CallExpression,
    StringLiteral,
    NumberLiteral,
}

#[derive(Debug,PartialEq,Clone)]
pub enum Node {
    Program { body: Vec<Node> },
    CallExpression { name: String, params: Vec<Node> },
    StringLiteral(String),
    NumberLiteral(String),
}

impl Node {
    fn get_type(&self) -> NodeType {
        match *self {
            Node::Program { .. } => NodeType::Program,
            Node::CallExpression { .. } => NodeType::CallExpression,
            Node::StringLiteral(_) => NodeType::StringLiteral,
            Node::NumberLiteral(_) => NodeType::NumberLiteral,
        }
    }
}

pub fn parser(tokens: Vec<Token>) -> Result<Node, String> {
    fn walk(token: Token, token_iter: &mut Peekable<IntoIter<Token>>) -> Result<Node, String> {
        match token {
            Token::Number(value) => Ok(Node::NumberLiteral(value)),
            Token::String(value) => Ok(Node::StringLiteral(value)),
            Token::ParenOpening => {
                if let Some(token) = token_iter.next() {
                    match token {
                        Token::Name(name) => {
                            let mut params: Vec<Node> = vec![];

                            while match token_iter.peek() {
                                      Some(&Token::ParenClosing) |
                                      None => false,
                                      _ => true,
                                  } {
                                match walk(token_iter.next().unwrap(), token_iter) {
                                    Ok(nodes) => params.push(nodes),
                                    Err(value) => return Err(value),
                                }
                            }

                            // skip Token::ParenClosing
                            token_iter.next().unwrap();

                            Ok(Node::CallExpression {
                                   name: name,
                                   params: params,
                               })
                        }
                        _ => {
                            return Err(format!("{:?} isn't followed by a {:?}.",
                                               Token::ParenOpening,
                                               Token::Name("example".to_string())))
                        }
                    }
                } else {
                    return Err(format!("{:?} isn't followed by a node.", Token::ParenOpening));
                }
            }
            _ => {
                return Err(format!("I don't know what this token is or this is a token which \
                                    should be covered elsewhere: {:?}",
                                   token))
            }
        }
    }

    let mut body: Vec<Node> = vec![];

    let mut token_iter = tokens.into_iter().peekable();
    while let Some(token) = token_iter.next() {
        match walk(token, &mut token_iter) {
            Ok(nodes) => body.push(nodes),
            Err(value) => return Err(value),
        }
    }

    Ok(Node::Program { body: body })
}

pub struct Visitor {
    pub enter: Option<Box<Fn(&Node, Option<&Node>, &mut TransformerContext)>>,
    pub exit: Option<Box<Fn(&Node, Option<&Node>, &mut TransformerContext)>>,
}

pub fn traverser(ast: Node, mut context: &mut TransformerContext) {
    fn traverse_nodes(nodes: &Vec<Node>,
                      parent: Option<&Node>,
                      context: &mut TransformerContext) {
        for node in nodes {
            traverse_node(&node, parent, context);
        }
    };

    fn traverse_node(node: &Node, parent: Option<&Node>, context: &mut TransformerContext) {
        let visitor = context.visitors.get(&node.get_type());

        if visitor.is_some() {
            if let Some(ref enter) = visitor.unwrap().enter {
                enter(&node, parent, context);
            }
        }

        match *node {
            Node::Program { ref body } => traverse_nodes(body, Some(node), context),
            Node::CallExpression { ref params, .. } => traverse_nodes(params, Some(node), context),
            _ => {}
            //_ => println!("We can't have an unknown node here!"),
        }

        if visitor.is_some() {
            if let Some(ref exit) = visitor.unwrap().exit {
                exit(&node, parent, context);
            }
        }
    };

    traverse_node(&ast, None, &mut context);
}

#[derive(Debug,PartialEq,Clone)]
pub enum Callee {
    Identifier(String),
}

#[derive(Debug,PartialEq,Clone)]
pub enum TransformedNode {
    Program { body: Vec<TransformedNode> },
    ExpressionStatement { expression: Box<TransformedNode> },
    CallExpression {
        callee: Callee,
        arguments: Vec<TransformedNode>,
    },
    StringLiteral(String),
    NumberLiteral(String),
}

pub struct TransformerContext {
    nodes: Vec<TransformedNode>,
    visitors: HashMap<NodeType, Visitor>,
}

pub fn transformer(ast: Node) -> TransformedNode {
    let mut visitors = HashMap::new();

    visitors.insert(
        NodeType::NumberLiteral,
        Visitor {
            enter: Some(Box::new(|node: &Node, parent: Option<&Node>, context: &mut TransformerContext| {
                if let &Node::NumberLiteral(ref value) = node {
                    context.nodes.push(TransformedNode::NumberLiteral(value.to_string()));
                }
            })),
            exit: None,
        }
    );

    let nodes: Vec<TransformedNode> = vec![];

    let mut context = TransformerContext {
        nodes: nodes,
        visitors: visitors
    };

    traverser(ast, &mut context);

    TransformedNode::Program { body: nodes }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![unstable]

//! A library for setting current values for stack scope,
//! such as application structure.

use std::rc::Rc;
use std::cell::RefCell;
use std::ops::{ Deref, DerefMut };

impl<'a, T, U: GetFrom<T>> GetFrom<&'a RefCell<T>> for U {
    #[inline(always)]
    fn get_from(obj: & &'a RefCell<T>) -> U {
        GetFrom::get_from(obj.borrow().deref())
    }
}

impl<T, U: GetFrom<T>> GetFrom<Rc<RefCell<T>>> for U {
    #[inline(always)]
    fn get_from(obj: &Rc<RefCell<T>>) -> U {
        GetFrom::get_from(obj.borrow().deref())
    }
}

impl<'a, F, T: SetAt<F>> SetAt<&'a RefCell<F>> for T {
    #[inline(always)]
    fn set_at(self, obj: &mut &'a RefCell<F>) {
        self.set_at(obj.borrow_mut().deref_mut())
    }
}

impl<F, T: SetAt<F>> SetAt<Rc<RefCell<F>>> for T {
    #[inline(always)]
    fn set_at(self, obj: &mut Rc<RefCell<F>>) {
        self.set_at(obj.borrow_mut().deref_mut())
    }
}

impl<'a, F, T: ActOn<F, U>, U> ActOn<&'a RefCell<F>, U> for T {
    #[inline(always)]
    fn act_on(self, obj: &mut &'a RefCell<F>) -> U {
        self.act_on(obj.borrow_mut().deref_mut())
    }
}

impl<F, T: ActOn<F, U>, U> ActOn<Rc<RefCell<F>>, U> for T {
    #[inline(always)]
    fn act_on(self, obj: &mut Rc<RefCell<F>>) -> U {
        self.act_on(obj.borrow_mut().deref_mut())
    }
}

/// Something that can be set at an object.
#[unstable]
pub trait SetAt<F> {
    /// Modify `F` with self.
    fn set_at(self, &mut F);
}

/// Automatically implemented through the `SetAt` trait.
#[unstable]
pub trait Set<T> {
    /// Set value.
    fn set(mut self, val: T) -> Self;

    /// Set value through mutable reference.
    fn set_mut(&mut self, val: T) -> &mut Self;
}

impl<T, U: SetAt<T>> Set<U> for T {
    #[inline(always)]
    fn set(mut self, val: U) -> T {
        val.set_at(&mut self);
        self
    }

    #[inline(always)]
    fn set_mut(&mut self, val: U) -> &mut T {
        val.set_at(self);
        self
    }
}

/// Something that can be retrieved from another object.
#[unstable]
pub trait GetFrom<T> {
    /// Gets value from object.
    fn get_from(obj: &T) -> Self;
}

/// Automatically implemented through the `GetFrom` trait.
#[unstable]
pub trait Get<T> {
    /// Returns new value.
    fn get(&self) -> T;
}

impl<T, U: GetFrom<T>> Get<U> for T {
    #[inline(always)]
    fn get(&self) -> U {
        GetFrom::get_from(self)
    }
}

/// Does something to an object.
#[unstable]
pub trait ActOn<T, U> {
    /// Does something to an object.
    fn act_on(self, &mut T) -> U;
}

/// Automatically implemented through the `ActOn` trait.
#[unstable]
pub trait Action<T, U> {
    /// Does something.
    fn action(&mut self, val: T) -> U;
}

impl<T, U: ActOn<T, V>, V> Action<U, V> for T {
    #[inline(always)]
    fn action(&mut self, val: U) -> V {
        val.act_on(self)
    }
}

<commit_msg>Redesign for new trait rules<commit_after>#![deny(missing_docs)]
#![unstable]

//! A library for setting current values for stack scope,
//! such as application structure.

use std::rc::Rc;
use std::cell::RefCell;
use std::ops::{ Deref, DerefMut };

impl<'a, T, U> GetFrom for (U, &'a RefCell<T>)
    where
        (U, T): GetFrom<Property = U, Object = T>
{
    type Property = U;
    type Object = &'a RefCell<T>;

    #[inline(always)]
    fn get_from(_: Me<Self>, obj: & &'a RefCell<T>) -> U {
        GetFrom::get_from(Me::<(U, T)>, obj.borrow().deref())
    }
}

impl<T, U> GetFrom for (U, Rc<RefCell<T>>)
    where
        (U, T): GetFrom<Property = U, Object = T>
{
    type Property = U;
    type Object = Rc<RefCell<T>>;

    #[inline(always)]
    fn get_from(_: Me<Self>, obj: &Rc<RefCell<T>>) -> U {
        GetFrom::get_from(Me::<(U, T)>, obj.borrow().deref())
    }
}

impl<'a, F, T> SetAt for (T, &'a RefCell<F>)
    where
        (T, F): SetAt<Property = T, Object = F>
{
    type Property = T;
    type Object = &'a RefCell<F>;

    #[inline(always)]
    fn set_at(_: Me<Self>, val: T, obj: &mut &'a RefCell<F>) {
        SetAt::set_at(Me::<(T, F)>, val, obj.borrow_mut().deref_mut())
    }
}

impl<F, T> SetAt for (T, Rc<RefCell<F>>)
    where
        (T, F): SetAt<Property = T, Object = F>
{
    type Property = T;
    type Object = Rc<RefCell<F>>;

    #[inline(always)]
    fn set_at(_: Me<Self>, val: T, obj: &mut Rc<RefCell<F>>) {
        SetAt::set_at(Me::<(T, F)>, val, obj.borrow_mut().deref_mut())
    }
}

impl<'a, F, A, V> ActOn<V> for (A, &'a RefCell<F>)
    where
        (A, F): ActOn<V, Action = A, Object = F>
{
    type Action = A;
    type Object = &'a RefCell<F>;

    #[inline(always)]
    fn act_on(_: Me<Self>, action: A, obj: &mut &'a RefCell<F>) -> V {
        ActOn::act_on(Me::<(A, F)>, action, obj.borrow_mut().deref_mut())
    }
}

impl<F, A, V> ActOn<V> for (A, Rc<RefCell<F>>)
    where
        (A, F): ActOn<V, Action = A, Object = F>
{
    type Action = A;
    type Object = Rc<RefCell<F>>;

    #[inline(always)]
    fn act_on(_: Me<Self>, action: A, obj: &mut Rc<RefCell<F>>) -> V {
        ActOn::act_on(Me::<(A, F)>, action, obj.borrow_mut().deref_mut())
    }
}

/// Used to solve problems when calling static methods on traits.
/// Calling static methods is necessary to solve implementation rules
/// when reexporting property types.
pub struct Me<T>;

/// Something that can be set at an object.
///
/// Must be implemented on a `(Property, Object)`
#[unstable]
pub trait SetAt {
    type Property;
    type Object;

    /// Modify `F` with self.
    fn set_at(
        me: Me<Self>,
        val: <Self as SetAt>::Property,
        obj: &mut <Self as SetAt>::Object
    );
}

/// Automatically implemented through the `SetAt` trait.
#[unstable]
pub trait Set<T> {
    /// Set value.
    fn set(mut self, val: T) -> Self;

    /// Set value through mutable reference.
    fn set_mut(&mut self, val: T) -> &mut Self;
}

impl<T, U> Set<U> for T
    where
        (U, T): SetAt<Property = U, Object = T>,
{
    #[inline(always)]
    fn set(mut self, val: U) -> T {
        SetAt::set_at(Me::<(U, T)>, val, &mut self);
        self
    }

    #[inline(always)]
    fn set_mut(&mut self, val: U) -> &mut T {
        SetAt::set_at(Me::<(U, T)>, val, self);
        self
    }
}

/// Something that can be retrieved from another object.
#[unstable]
pub trait GetFrom {
    type Property;
    type Object;

    /// Gets value from object.
    fn get_from(
        me: Me<Self>,
        obj: &<Self as GetFrom>::Object
    ) -> <Self as GetFrom>::Property;
}

/// Automatically implemented through the `GetFrom` trait.
#[unstable]
pub trait Get<T> {
    /// Returns new value.
    fn get(&self) -> T;
}

impl<T, U> Get<U> for T
    where
        (U, T): GetFrom<Property = U, Object = T>
{
    #[inline(always)]
    fn get(&self) -> U {
        GetFrom::get_from(Me::<(U, T)>, self)
    }
}

/// Does something to an object.
#[unstable]
pub trait ActOn<T> {
    type Action;
    type Object;

    /// Does something to an object.
    fn act_on(
        me: Me<Self>,
        action: <Self as ActOn<T>>::Action,
        obj: &mut <Self as ActOn<T>>::Object
    ) -> T;
}

/// Automatically implemented through the `ActOn` trait.
#[unstable]
pub trait Action<A, V> {
    /// Does something.
    fn action(&mut self, val: A) -> V;
}

impl<T, A, V> Action<A, V> for T
    where
        (A, T): ActOn<V, Action = A, Object = T>
{
    #[inline(always)]
    fn action(&mut self, action: A) -> V {
        ActOn::act_on(Me::<(A, T)>, action, self)
    }
}

<|endoftext|>


<commit_before>#![feature(core_intrinsics)]

use matchers::Matcher;
use dsl::*;

mod matchers;
mod dsl;

use std::fmt::Debug;

pub struct Expectation<Lhs: Debug>(Lhs);

impl<Lhs: Debug> Expectation<Lhs> {
    pub fn is<T>(&self, matcher: Box<T>) where T: Matcher<Lhs> {
        self.to(matcher)
    }

    pub fn to<T>(&self, matcher: Box<T>) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }
}

<commit_msg>Create negation match methods<commit_after>#![feature(core_intrinsics)]

use matchers::Matcher;
use dsl::*;

mod matchers;
mod dsl;

use std::fmt::Debug;

pub struct Expectation<Lhs: Debug>(Lhs);

impl<Lhs: Debug> Expectation<Lhs> {
    pub fn is<T>(&self, matcher: Box<T>) where T: Matcher<Lhs> {
        self.to(matcher)
    }

    pub fn is_not<T>(&self, matcher: Box<T>) where T: Matcher<Lhs> {
        self.to_not(matcher)
    }

    pub fn to<T>(&self, matcher: Box<T>) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }

    pub fn to_not<T>(&self, matcher: Box<T>) where T: Matcher<Lhs> {
        if matcher.matches(&self.0) {
            panic!(matcher.negated_fail_msg(&self.0))
        }
    }
}

<|endoftext|>