<commit_before>// Copyright (c) 2017 fd developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

extern crate ansi_term;
extern crate atty;
#[macro_use]
extern crate clap;
extern crate ignore;
#[macro_use]
extern crate lazy_static;
#[cfg(all(unix, not(target_os = "redox")))]
extern crate libc;
extern crate num_cpus;
extern crate regex;
extern crate regex_syntax;

pub mod fshelper;
pub mod lscolors;
mod app;
mod exec;
mod internal;
mod output;
mod walk;

#[cfg(windows)]
mod windows;

use std::env;
use std::error::Error;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time;

use atty::Stream;
use regex::{RegexBuilder, RegexSetBuilder};

use exec::CommandTemplate;
use internal::{error, pattern_has_uppercase_char, transform_args_with_exec, FdOptions};
use lscolors::LsColors;
use walk::FileType;

fn main() {
    let checked_args = transform_args_with_exec(env::args_os());
    let matches = app::build_app().get_matches_from(checked_args);

    // Get the search pattern
    let pattern = matches.value_of("pattern").unwrap_or("");

    // Get the current working directory
    let current_dir = Path::new(".");
    if !fshelper::is_dir(current_dir) {
        error("Error: could not get current directory.");
    }

    //Get one or more root directories to search.
    let mut dir_vec: Vec<_> = match matches.values_of("path") {
        Some(paths) => paths
            .map(|path| {
                let path_buffer = PathBuf::from(path);
                if !fshelper::is_dir(&path_buffer) {
                    error(&format!(
                        "Error: '{}' is not a directory.",
                        path_buffer.to_string_lossy()
                    ));
                }
                path_buffer
            })
            .collect::<Vec<_>>(),
        None => vec![current_dir.to_path_buf()],
    };

    if matches.is_present("absolute-path") {
        dir_vec = dir_vec
            .iter()
            .map(|path_buffer| fshelper::absolute_path(path_buffer).unwrap())
            .collect();
    }

    // Treat pattern as literal string if '--fixed-strings' is used
    let pattern_regex = if matches.is_present("fixed-strings") {
        regex::escape(pattern)
    } else {
        String::from(pattern)
    };

    // The search will be case-sensitive if the command line flag is set or
    // if the pattern has an uppercase character (smart case).
    let case_sensitive = !matches.is_present("ignore-case")
        && (matches.is_present("case-sensitive") || pattern_has_uppercase_char(&pattern_regex));

    let colored_output = match matches.value_of("color") {
        Some("always") => true,
        Some("never") => false,
        _ => atty::is(Stream::Stdout),
    };

    #[cfg(windows)]
    let colored_output = colored_output && windows::enable_colored_output();

    let ls_colors = if colored_output {
        Some(
            env::var("LS_COLORS")
                .ok()
                .map(|val| LsColors::from_string(&val))
                .unwrap_or_default(),
        )
    } else {
        None
    };

    let command = matches.values_of("exec").map(CommandTemplate::new);

    let config = FdOptions {
        case_sensitive,
        search_full_path: matches.is_present("full-path"),
        ignore_hidden: !(matches.is_present("hidden")
            || matches.occurrences_of("rg-alias-hidden-ignore") >= 2),
        read_ignore: !(matches.is_present("no-ignore")
            || matches.is_present("rg-alias-hidden-ignore")),
        read_gitignore: !(matches.is_present("no-ignore")
            || matches.is_present("rg-alias-hidden-ignore")
            || matches.is_present("no-ignore-vcs")),
        follow_links: matches.is_present("follow"),
        null_separator: matches.is_present("null_separator"),
        max_depth: matches
            .value_of("depth")
            .and_then(|n| usize::from_str_radix(n, 10).ok()),
        threads: std::cmp::max(
            matches
                .value_of("threads")
                .and_then(|n| usize::from_str_radix(n, 10).ok())
                .unwrap_or_else(num_cpus::get),
            1,
        ),
        max_buffer_time: matches
            .value_of("max-buffer-time")
            .and_then(|n| u64::from_str_radix(n, 10).ok())
            .map(time::Duration::from_millis),
        ls_colors,
        file_types: match matches.values_of("file-type") {
            None => vec![
                FileType::RegularFile,
                FileType::Directory,
                FileType::SymLink,
            ].into_iter()
                .collect(),
            Some(values) => values
                .map(|value| match value {
                    "f" | "file" => FileType::RegularFile,
                    "d" | "directory" => FileType::Directory,
                    "l" | "symlink" => FileType::SymLink,
                    _ => FileType::RegularFile,
                })
                .collect(),
        },
        extensions: matches.values_of("extension").map(|exts| {
            let patterns = exts.map(|e| e.trim_left_matches('.'))
                .map(|e| format!(r".\.{}$", regex::escape(e)));
            match RegexSetBuilder::new(patterns)
                .case_insensitive(true)
                .build()
            {
                Ok(re) => re,
                Err(err) => error(err.description()),
            }
        }),
        command,
        exclude_patterns: matches
            .values_of("exclude")
            .map(|v| v.map(|p| String::from("!") + p).collect())
            .unwrap_or_else(|| vec![]),
    };

    match RegexBuilder::new(&pattern_regex)
        .case_insensitive(!config.case_sensitive)
        .dot_matches_new_line(true)
        .build()
    {
        Ok(re) => walk::scan(&dir_vec, Arc::new(re), Arc::new(config)),
        Err(err) => error(err.description()),
    }
}
<commit_msg>Fixes: #234 Giving suggestion to use `--fixed-strings` in case user passes invalid metacharacters as a regex.<commit_after>// Copyright (c) 2017 fd developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

extern crate ansi_term;
extern crate atty;
#[macro_use]
extern crate clap;
extern crate ignore;
#[macro_use]
extern crate lazy_static;
#[cfg(all(unix, not(target_os = "redox")))]
extern crate libc;
extern crate num_cpus;
extern crate regex;
extern crate regex_syntax;

pub mod fshelper;
pub mod lscolors;
mod app;
mod exec;
mod internal;
mod output;
mod walk;

#[cfg(windows)]
mod windows;

use std::env;
use std::error::Error;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time;

use atty::Stream;
use regex::{RegexBuilder, RegexSetBuilder};

use exec::CommandTemplate;
use internal::{error, pattern_has_uppercase_char, transform_args_with_exec, FdOptions};
use lscolors::LsColors;
use walk::FileType;

fn main() {
    let checked_args = transform_args_with_exec(env::args_os());
    let matches = app::build_app().get_matches_from(checked_args);

    // Get the search pattern
    let pattern = matches.value_of("pattern").unwrap_or("");

    // Get the current working directory
    let current_dir = Path::new(".");
    if !fshelper::is_dir(current_dir) {
        error("Error: could not get current directory.");
    }

    //Get one or more root directories to search.
    let mut dir_vec: Vec<_> = match matches.values_of("path") {
        Some(paths) => paths
            .map(|path| {
                let path_buffer = PathBuf::from(path);
                if !fshelper::is_dir(&path_buffer) {
                    error(&format!(
                        "Error: '{}' is not a directory.",
                        path_buffer.to_string_lossy()
                    ));
                }
                path_buffer
            })
            .collect::<Vec<_>>(),
        None => vec![current_dir.to_path_buf()],
    };

    if matches.is_present("absolute-path") {
        dir_vec = dir_vec
            .iter()
            .map(|path_buffer| fshelper::absolute_path(path_buffer).unwrap())
            .collect();
    }

    // Treat pattern as literal string if '--fixed-strings' is used
    let pattern_regex = if matches.is_present("fixed-strings") {
        regex::escape(pattern)
    } else {
        String::from(pattern)
    };

    // The search will be case-sensitive if the command line flag is set or
    // if the pattern has an uppercase character (smart case).
    let case_sensitive = !matches.is_present("ignore-case")
        && (matches.is_present("case-sensitive") || pattern_has_uppercase_char(&pattern_regex));

    let colored_output = match matches.value_of("color") {
        Some("always") => true,
        Some("never") => false,
        _ => atty::is(Stream::Stdout),
    };

    #[cfg(windows)]
    let colored_output = colored_output && windows::enable_colored_output();

    let ls_colors = if colored_output {
        Some(
            env::var("LS_COLORS")
                .ok()
                .map(|val| LsColors::from_string(&val))
                .unwrap_or_default(),
        )
    } else {
        None
    };

    let command = matches.values_of("exec").map(CommandTemplate::new);

    let config = FdOptions {
        case_sensitive,
        search_full_path: matches.is_present("full-path"),
        ignore_hidden: !(matches.is_present("hidden")
            || matches.occurrences_of("rg-alias-hidden-ignore") >= 2),
        read_ignore: !(matches.is_present("no-ignore")
            || matches.is_present("rg-alias-hidden-ignore")),
        read_gitignore: !(matches.is_present("no-ignore")
            || matches.is_present("rg-alias-hidden-ignore")
            || matches.is_present("no-ignore-vcs")),
        follow_links: matches.is_present("follow"),
        null_separator: matches.is_present("null_separator"),
        max_depth: matches
            .value_of("depth")
            .and_then(|n| usize::from_str_radix(n, 10).ok()),
        threads: std::cmp::max(
            matches
                .value_of("threads")
                .and_then(|n| usize::from_str_radix(n, 10).ok())
                .unwrap_or_else(num_cpus::get),
            1,
        ),
        max_buffer_time: matches
            .value_of("max-buffer-time")
            .and_then(|n| u64::from_str_radix(n, 10).ok())
            .map(time::Duration::from_millis),
        ls_colors,
        file_types: match matches.values_of("file-type") {
            None => vec![
                FileType::RegularFile,
                FileType::Directory,
                FileType::SymLink,
            ].into_iter()
                .collect(),
            Some(values) => values
                .map(|value| match value {
                    "f" | "file" => FileType::RegularFile,
                    "d" | "directory" => FileType::Directory,
                    "l" | "symlink" => FileType::SymLink,
                    _ => FileType::RegularFile,
                })
                .collect(),
        },
        extensions: matches.values_of("extension").map(|exts| {
            let patterns = exts.map(|e| e.trim_left_matches('.'))
                .map(|e| format!(r".\.{}$", regex::escape(e)));
            match RegexSetBuilder::new(patterns)
                .case_insensitive(true)
                .build()
            {
                Ok(re) => re,
                Err(err) => error(err.description()),
            }
        }),
        command,
        exclude_patterns: matches
            .values_of("exclude")
            .map(|v| v.map(|p| String::from("!") + p).collect())
            .unwrap_or_else(|| vec![]),
    };

    match RegexBuilder::new(&pattern_regex)
        .case_insensitive(!config.case_sensitive)
        .dot_matches_new_line(true)
        .build()
    {
        Ok(re) => walk::scan(&dir_vec, Arc::new(re), Arc::new(config)),
        Err(err) => error(
            format!(
                "{}\nHint: You can use the '--fixed-strings' option to search for a \
                            literal string instead of a regular expression",
                err.description()
            ).as_str(),
        ),
    }
}
<|endoftext|>


<commit_before>extern crate socket;

use socket::{AF_INET, Socket, SOCK_DGRAM, IP_MULTICAST_TTL, IPPROTO_IP};
use std::collections::HashSet;
use std::net::SocketAddr;
use std::str::FromStr;
use std::sync::{Arc, mpsc};
use std::thread;
use std::time::Instant;

fn main() {
    Discover::new().start(None, Some(4))
}

struct Discover {
    pub devices: Vec<String>,
    multicast: SocketAddr,
    socket: Arc<Socket>
}

impl Discover {
    pub fn new() -> Self {
        Discover {
            devices: Vec::new(),
            multicast: SocketAddr::from_str("239.255.255.250:1900").unwrap(),
            socket: Discover::create_socket()
        }
    }

    fn create_socket() -> Arc<Socket> {
        let socket = Socket::new(AF_INET, SOCK_DGRAM, 0).unwrap();
        let _ = socket.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL, 4);

        Arc::new(socket)
    }

    fn send_search(&self) {
        let player_search = r#"M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 1
ST: urn:schemas-upnp-org:device:ZonePlayer:1"#.as_bytes();
        let _ = self.socket.sendto(player_search, 0, &self.multicast);
    }

    pub fn start(self, timeout: Option<u32>, device_count: Option<usize>) {
        let timeout = match timeout {
            Some(value) => { value }
            None => 5
        };
        let device_count = match device_count {
            Some(value) => { value }
            None => std::u32::MAX as usize
        };

        let time = Instant::now();

        self.send_search();
        let mut devices = HashSet::new();
        let socket = self.socket.clone();
        while time.elapsed().as_secs() < timeout as u64 && devices.len() < device_count {
            let socket = socket.clone();
            let (sender, receiver) = mpsc::channel();
            let _ = thread::spawn(move ||
                {
                    match socket.recvfrom(1024, 0) {
                        Ok((__addr, _data)) => {
                            let _ = sender.send((__addr, _data));
                        }
                        Err(_) => {}
                    }
                }
            );

            let (_addr, data) = match receiver.recv_timeout(std::time::Duration::new(0, 500000000)) {
                Ok((_addr, data)) => (_addr, data),
                Err(_) => continue
            };
            if devices.contains(&_addr.ip()) || data.is_empty() {
                println!("{:?}", &_addr.ip());
                continue
            }

            let data = String::from_utf8_lossy(&data);
            if data.contains("Sonos") {
                devices.insert(_addr.ip());
            }
        }
        println!("{:#?}", devices.len());
    }
}

/*impl Drop for Discover {
    fn drop(&mut self) {
        // Socket closes on drop automatically, better safe than sorry
        let _ = self.socket.close();
    }
}*/

impl Default for Discover {
    fn default() -> Self {
        Discover::new()
    }
}
<commit_msg>Make `Discover` public<commit_after>extern crate socket;

use socket::{AF_INET, Socket, SOCK_DGRAM, IP_MULTICAST_TTL, IPPROTO_IP};
use std::collections::HashSet;
use std::net::SocketAddr;
use std::str::FromStr;
use std::sync::{Arc, mpsc};
use std::thread;
use std::time::Instant;

fn main() {
    Discover::new().start(None, Some(4))
}

pub struct Discover {
    pub devices: Vec<String>,
    multicast: SocketAddr,
    socket: Arc<Socket>
}

impl Discover {
    pub fn new() -> Self {
        Discover {
            devices: Vec::new(),
            multicast: SocketAddr::from_str("239.255.255.250:1900").unwrap(),
            socket: Discover::create_socket()
        }
    }

    fn create_socket() -> Arc<Socket> {
        let socket = Socket::new(AF_INET, SOCK_DGRAM, 0).unwrap();
        let _ = socket.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL, 4);

        Arc::new(socket)
    }

    fn send_search(&self) {
        let player_search = r#"M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 1
ST: urn:schemas-upnp-org:device:ZonePlayer:1"#.as_bytes();
        let _ = self.socket.sendto(player_search, 0, &self.multicast);
    }

    pub fn start(self, timeout: Option<u32>, device_count: Option<usize>) {
        let timeout = match timeout {
            Some(value) => { value }
            None => 5
        };
        let device_count = match device_count {
            Some(value) => { value }
            None => std::u32::MAX as usize
        };

        let time = Instant::now();

        self.send_search();
        let mut devices = HashSet::new();
        let socket = self.socket.clone();
        while time.elapsed().as_secs() < timeout as u64 && devices.len() < device_count {
            let socket = socket.clone();
            let (sender, receiver) = mpsc::channel();
            let _ = thread::spawn(move ||
                {
                    match socket.recvfrom(1024, 0) {
                        Ok((__addr, _data)) => {
                            let _ = sender.send((__addr, _data));
                        }
                        Err(_) => {}
                    }
                }
            );

            let (_addr, data) = match receiver.recv_timeout(std::time::Duration::new(0, 500000000)) {
                Ok((_addr, data)) => (_addr, data),
                Err(_) => continue
            };
            if devices.contains(&_addr.ip()) || data.is_empty() {
                println!("{:?}", &_addr.ip());
                continue
            }

            let data = String::from_utf8_lossy(&data);
            if data.contains("Sonos") {
                devices.insert(_addr.ip());
            }
        }
        println!("{:#?}", devices.len());
    }
}

/*impl Drop for Discover {
    fn drop(&mut self) {
        // Socket closes on drop automatically, better safe than sorry
        let _ = self.socket.close();
    }
}*/

impl Default for Discover {
    fn default() -> Self {
        Discover::new()
    }
}
<|endoftext|>


<commit_before>// TODO: many items from tokio-core::io have been deprecated in favour of tokio-io
#![allow(deprecated)]

#[cfg(debug_assertions)]
#[macro_use] extern crate log;
#[cfg(debug_assertions)]
extern crate env_logger;
extern crate futures;
extern crate getopts;
extern crate librespot;
extern crate tokio_core;
extern crate tokio_signal;

#[cfg(debug_assertions)]
use env_logger::LogBuilder;
use futures::{Future, Async, Poll, Stream};
#[cfg(debug_assertions)]
use std::env;
use std::io::{self, stderr, Write};
use std::path::PathBuf;
use std::process::exit;
use tokio_core::reactor::{Handle, Core};
use tokio_core::io::IoStream;
use std::mem;

use librespot::spirc::{Spirc, SpircTask};
use librespot::core::authentication::{get_credentials, Credentials};
#[cfg(not(target_os="windows"))]
use librespot::discovery::{discovery, DiscoveryStream};
use librespot::audio_backend;
use librespot::core::cache::Cache;
use librespot::core::config::{Bitrate, DeviceType, PlayerConfig, SessionConfig, ConnectConfig};
use librespot::player::Player;
use librespot::core::session::Session;
use librespot::mixer;
use librespot::core::util::SpotifyId;

const VERSION: &'static str = concat!(env!("CARGO_PKG_NAME"), " v", env!("CARGO_PKG_VERSION"));

fn usage(program: &str, opts: &getopts::Options) -> String {
	println!("{}", VERSION.to_string());

	let brief = format!("Usage: {} [options]", program);
	opts.usage(&brief)
}

#[cfg(debug_assertions)]
fn setup_logging(verbose: bool) {
	let mut builder = LogBuilder::new();
	match env::var("RUST_LOG") {
		Ok(config) => {
			builder.parse(&config);
			builder.init().unwrap();

			if verbose {
				warn!("`--verbose` flag overidden by `RUST_LOG` environment variable");
			}
		}
		Err(_) => {
			if verbose {
				builder.parse("mdns=info,librespot=trace");
			} else {
				builder.parse("mdns=error,librespot=warn");
			}
			builder.init().unwrap();
		}
	}
}

#[derive(Clone)]
struct Setup {
	cache: Option<Cache>,
    player_config: PlayerConfig,
    session_config: SessionConfig,
    connect_config: ConnectConfig,
	credentials: Option<Credentials>,
	authenticate: bool,
	enable_discovery: bool,

	get_token: bool,
	client_id: Option<String>,
	scope: Option<String>,

	single_track: Option<String>,
	start_position: u32,
}

fn setup(args: &[String]) -> Setup {
	let mut opts = getopts::Options::new();
	opts.optopt("c", "cache", "Path to a directory where files will be cached.", "CACHE")
		.optflag("", "enable-audio-cache", "Enable caching of the audio data.")
		.optflag("", "disable-audio-cache", "(Only here fore compatibility with librespot - audio cache is disabled by default).")
		.reqopt("n", "name", "Device name", "NAME")
		.optopt("", "onstart", "Run PROGRAM when playback is about to begin.", "PROGRAM")
		.optopt("", "onstop", "Run PROGRAM when playback has ended.", "PROGRAM")
		.optopt("", "single-track", "Play a single track ID and exit.", "ID")
		.optopt("", "start-position", "Position (in ms) where playback should be started. Only valid with the --single-track option.", "STARTPOSITION")
		.optopt("u", "username", "Username to sign in with", "USERNAME")
		.optopt("p", "password", "Password", "PASSWORD")
		.optflag("a", "authenticate", "Authenticate given username and password. Make sure you define a cache folder to store credentials.")
		.optflag("", "disable-discovery", "Disable discovery mode")
		.optflag("t", "get-token", "Get oauth token to be used with the web API etc.")
		.optopt("i", "client-id", "A Spotify client_id to be used to get the oauth token. Required with the --get-token request.", "CLIENT_ID")
		.optopt("", "scope", "The scopes you want to have access to with the oauth token.", "SCOPE")
		.optflag("x", "check", "Run quick internal check");

	#[cfg(debug_assertions)]
	opts.optflag("v", "verbose", "Enable verbose output");

	let matches = match opts.parse(&args[1..]) {
		Ok(m) => m,
		Err(f) => {
			writeln!(stderr(), "error: {}\n{}", f.to_string(), usage(&args[0], &opts)).unwrap();
			exit(1);
		}
	};

	if matches.opt_present("check") {
		println!("ok {}", VERSION.to_string());
		exit(1);
	}

	#[cfg(debug_assertions)]
	{
		let verbose = matches.opt_present("verbose");
		setup_logging(verbose);
	}

	let name = matches.opt_str("name").unwrap();

	let use_audio_cache = matches.opt_present("enable-audio-cache") && !matches.opt_present("disable-audio-cache");

	let cache = matches.opt_str("c").map(|cache_location| {
		Cache::new(PathBuf::from(cache_location), use_audio_cache)
	});

	let credentials = {
		let cached_credentials = cache.as_ref().and_then(Cache::credentials);

		get_credentials(
			matches.opt_str("username"),
			matches.opt_str("password"),
			cached_credentials
		)
	};

	let authenticate = matches.opt_present("authenticate");

#[cfg(not(target_os="windows"))]
	let enable_discovery = !matches.opt_present("disable-discovery");
#[cfg(target_os="windows")]
	let enable_discovery = false;

	let start_position = matches.opt_str("start-position")
		.unwrap_or("0".to_string())
		.parse().unwrap_or(0.0);

	let session_config = {
		let device_id = librespot::core::session::device_id(&name);

		SessionConfig {
			user_agent: VERSION.to_string(),
			device_id: device_id
		}
	};

	let player_config = {
		PlayerConfig {
			bitrate: Bitrate::Bitrate320,
			onstart: matches.opt_str("onstart"),
			onstop: matches.opt_str("onstop"),
		}
	};

	let connect_config = {
		ConnectConfig {
			name: name,
			device_type: DeviceType::default(),
		}
	};

	Setup {
		cache: cache,
		session_config: session_config,
		player_config: player_config,
		connect_config: connect_config,
		credentials: credentials,
		authenticate: authenticate,
		enable_discovery: enable_discovery,

		get_token: matches.opt_present("get-token"),
		client_id: matches.opt_str("client-id"),
		scope: matches.opt_str("scope"),

		single_track: matches.opt_str("single-track"),
		start_position: (start_position * 1000.0) as u32,
	}
}

struct Main {
	cache: Option<Cache>,
	session_config: SessionConfig,
	player_config: PlayerConfig,
	connect_config: ConnectConfig,
	handle: Handle,

#[cfg(not(target_os="windows"))]
	discovery: Option<DiscoveryStream>,
#[cfg(target_os="windows")]
	discovery: Option<String>,
	signal: IoStream<()>,

	spirc: Option<Spirc>,
	spirc_task: Option<SpircTask>,
	connect: Box<Future<Item=Session, Error=io::Error>>,

	player: Option<Player>,

	shutdown: bool,
	authenticate: bool,
}

impl Main {
	fn new(handle: Handle, setup: Setup) -> Main {
		let mut task = Main {
			handle: handle.clone(),
			cache: setup.cache,
			session_config: setup.session_config,
			player_config: setup.player_config,
			connect_config: setup.connect_config,

			connect: Box::new(futures::future::empty()),
			discovery: None,
			spirc: None,
			spirc_task: None,

			player: None,

			shutdown: false,
			authenticate: setup.authenticate,
			signal: tokio_signal::ctrl_c(&handle).flatten_stream().boxed(),
		};

		if setup.enable_discovery {
			let config = task.connect_config.clone();
			let device_id = task.session_config.device_id.clone();

			task.discovery = Some(discovery(&handle, config, device_id).unwrap());
		}

		if let Some(credentials) = setup.credentials {
			task.credentials(credentials);
		}

		task
	}

	fn credentials(&mut self, credentials: Credentials) {
		let config = self.session_config.clone();
		let handle = self.handle.clone();

		let connection = Session::connect(config, credentials, self.cache.clone(), handle);

		self.connect = connection;
		self.spirc = None;
		let task = mem::replace(&mut self.spirc_task, None);
		if let Some(task) = task {
			self.handle.spawn(task);
		}
	}
}

impl Future for Main {
	type Item = ();
	type Error = ();

	fn poll(&mut self) -> Poll<(), ()> {
		loop {
			let mut progress = false;

#[cfg(not(target_os="windows"))] {
			if let Some(Async::Ready(Some(creds))) = self.discovery.as_mut().map(|d| d.poll().unwrap()) {
				if let Some(ref spirc) = self.spirc {
					spirc.shutdown();
				}
				self.credentials(creds);

				progress = true;
			}
}

			if let Async::Ready(session) = self.connect.poll().unwrap() {
				if self.authenticate {
					if !self.shutdown {
						if let Some(ref spirc) = self.spirc {
							spirc.shutdown();
						}
						self.shutdown = true;
					} else {
						return Ok(Async::Ready(()));
					}
				}
				else {
					self.connect = Box::new(futures::future::empty());
					let player_config = self.player_config.clone();
					let connect_config = self.connect_config.clone();

					let mixer = (mixer::find(Some("softvol")).unwrap())();

					let audio_filter = mixer.get_audio_filter();
					let backend = audio_backend::find(None).unwrap();
					let player = Player::new(player_config, session.clone(), audio_filter, move || {
						(backend)(None)
					});

					self.player = Some(player.clone());

					let (spirc, spirc_task) = Spirc::new(connect_config, session, player, mixer);
					self.spirc = Some(spirc);
					self.spirc_task = Some(spirc_task);
				}

				progress = true;
			}

			if let Async::Ready(Some(())) = self.signal.poll().unwrap() {
				if !self.shutdown {
					if let Some(ref spirc) = self.spirc {
						spirc.shutdown();
					}
					self.shutdown = true;
				} else {
					return Ok(Async::Ready(()));
				}

				progress = true;
			}

			if let Some(ref mut spirc_task) = self.spirc_task {
				if let Async::Ready(()) = spirc_task.poll().unwrap() {
					if self.shutdown {
						return Ok(Async::Ready(()));
					} else {
						panic!("Spirc shut down unexpectedly");
					}
				}
			}

			if !progress {
				return Ok(Async::NotReady);
			}
		}
	}
}

fn main() {
	let mut core = Core::new().unwrap();
	let handle = core.handle();

	let args: Vec<String> = std::env::args().collect();
	let Setup { cache, session_config, player_config, connect_config, credentials, authenticate, enable_discovery, get_token, client_id, scope, single_track, start_position } = setup(&args.clone());

	if let Some(ref track_id) = single_track {
		match credentials {
			Some(credentials) => {
				let backend = audio_backend::find(None).unwrap();

				let track = SpotifyId::from_base62(
									track_id.replace("spotty://", "")
									.replace("spotify://", "")
									.replace("spotify:", "")
									.replace("track:", "")
									.as_str());

				let session = core.run(Session::connect(session_config.clone(), credentials, cache.clone(), handle)).unwrap();

				let player = Player::new(player_config, session.clone(), None, move || (backend)(None));

				core.run(player.load(track, true, start_position)).unwrap();
			}
			None => {
				println!("Missing credentials");
			}
		}
	}
	else if authenticate && !enable_discovery {
		core.run(Session::connect(session_config.clone(), credentials.unwrap(), cache.clone(), handle)).unwrap();
		println!("authorized");
	}
	else if get_token {
		if let Some(client_id) = client_id {
			let session = core.run(Session::connect(session_config, credentials.unwrap(), cache.clone(), handle)).unwrap();
			let scope = scope.unwrap_or("user-read-private,playlist-read-private,playlist-read-collaborative,playlist-modify-public,playlist-modify-private,user-follow-modify,user-follow-read,user-library-read,user-library-modify,user-top-read,user-read-recently-played".to_string());
			let url = format!("hm://keymaster/token/authenticated?client_id={}&scope={}", client_id, scope);
			core.run(session.mercury().get(url).map(move |response| {
				let data = response.payload.first().expect("Empty payload");
				let token = String::from_utf8(data.clone()).unwrap();
				println!("{}", token);
			}).boxed()).unwrap();
		}
		else {
			println!("Use --client-id to provide a CLIENT_ID");
		}
	}
	else {
		core.run(Main::new(handle, Setup { cache, session_config, player_config, connect_config, credentials, authenticate, enable_discovery, get_token, client_id, scope, single_track, start_position })).unwrap()
	}
}

<commit_msg>(manually) merge pull request #2 - thanks mnd999!<commit_after>// TODO: many items from tokio-core::io have been deprecated in favour of tokio-io
#![allow(deprecated)]

#[cfg(debug_assertions)]
#[macro_use] extern crate log;
#[cfg(debug_assertions)]
extern crate env_logger;
extern crate futures;
extern crate getopts;
extern crate librespot;
extern crate tokio_core;
extern crate tokio_signal;

#[cfg(debug_assertions)]
use env_logger::LogBuilder;
use futures::{Future, Async, Poll, Stream};
#[cfg(debug_assertions)]
use std::env;
use std::io::{self, stderr, Write};
use std::path::PathBuf;
use std::process::exit;
use tokio_core::reactor::{Handle, Core};
use tokio_core::io::IoStream;
use std::mem;

use librespot::spirc::{Spirc, SpircTask};
use librespot::core::authentication::{get_credentials, Credentials};
#[cfg(not(target_os="windows"))]
use librespot::discovery::{discovery, DiscoveryStream};
use librespot::audio_backend;
use librespot::core::cache::Cache;
use librespot::core::config::{Bitrate, DeviceType, PlayerConfig, SessionConfig, ConnectConfig};
use librespot::player::Player;
use librespot::core::session::Session;
use librespot::mixer;
use librespot::core::util::SpotifyId;

const VERSION: &'static str = concat!(env!("CARGO_PKG_NAME"), " v", env!("CARGO_PKG_VERSION"));

fn usage(program: &str, opts: &getopts::Options) -> String {
	println!("{}", VERSION.to_string());

	let brief = format!("Usage: {} [options]", program);
	opts.usage(&brief)
}

#[cfg(debug_assertions)]
fn setup_logging(verbose: bool) {
	let mut builder = LogBuilder::new();
	match env::var("RUST_LOG") {
		Ok(config) => {
			builder.parse(&config);
			builder.init().unwrap();

			if verbose {
				warn!("`--verbose` flag overidden by `RUST_LOG` environment variable");
			}
		}
		Err(_) => {
			if verbose {
				builder.parse("mdns=info,librespot=trace");
			} else {
				builder.parse("mdns=error,librespot=warn");
			}
			builder.init().unwrap();
		}
	}
}

#[derive(Clone)]
struct Setup {
	cache: Option<Cache>,
    player_config: PlayerConfig,
    session_config: SessionConfig,
    connect_config: ConnectConfig,
	credentials: Option<Credentials>,
	authenticate: bool,
	enable_discovery: bool,

	get_token: bool,
	client_id: Option<String>,
	scope: Option<String>,

	single_track: Option<String>,
	start_position: u32,
}

fn setup(args: &[String]) -> Setup {
	let mut opts = getopts::Options::new();
	opts.optopt("c", "cache", "Path to a directory where files will be cached.", "CACHE")
		.optflag("", "enable-audio-cache", "Enable caching of the audio data.")
		.optflag("", "disable-audio-cache", "(Only here fore compatibility with librespot - audio cache is disabled by default).")
		.reqopt("n", "name", "Device name", "NAME")
		.optopt("", "onstart", "Run PROGRAM when playback is about to begin.", "PROGRAM")
		.optopt("", "onstop", "Run PROGRAM when playback has ended.", "PROGRAM")
		.optopt("", "single-track", "Play a single track ID and exit.", "ID")
		.optopt("", "start-position", "Position (in ms) where playback should be started. Only valid with the --single-track option.", "STARTPOSITION")
		.optopt("u", "username", "Username to sign in with", "USERNAME")
		.optopt("p", "password", "Password", "PASSWORD")
		.optflag("a", "authenticate", "Authenticate given username and password. Make sure you define a cache folder to store credentials.")
		.optflag("", "disable-discovery", "Disable discovery mode")
		.optflag("t", "get-token", "Get oauth token to be used with the web API etc.")
		.optopt("i", "client-id", "A Spotify client_id to be used to get the oauth token. Required with the --get-token request.", "CLIENT_ID")
		.optopt("", "scope", "The scopes you want to have access to with the oauth token.", "SCOPE")
		.optflag("x", "check", "Run quick internal check");

	#[cfg(debug_assertions)]
	opts.optflag("v", "verbose", "Enable verbose output");

	let matches = match opts.parse(&args[1..]) {
		Ok(m) => m,
		Err(f) => {
			writeln!(stderr(), "error: {}\n{}", f.to_string(), usage(&args[0], &opts)).unwrap();
			exit(1);
		}
	};

	if matches.opt_present("check") {
		println!("ok {}", VERSION.to_string());
		exit(1);
	}

	#[cfg(debug_assertions)]
	{
		let verbose = matches.opt_present("verbose");
		setup_logging(verbose);
	}

	let name = matches.opt_str("name").unwrap();

	let use_audio_cache = matches.opt_present("enable-audio-cache") && !matches.opt_present("disable-audio-cache");

	let cache = matches.opt_str("c").map(|cache_location| {
		Cache::new(PathBuf::from(cache_location), use_audio_cache)
	});

	let credentials = {
		let cached_credentials = cache.as_ref().and_then(Cache::credentials);

		get_credentials(
			matches.opt_str("username"),
			matches.opt_str("password"),
			cached_credentials
		)
	};

	let authenticate = matches.opt_present("authenticate");

#[cfg(not(target_os="windows"))]
	let enable_discovery = !matches.opt_present("disable-discovery");
#[cfg(target_os="windows")]
	let enable_discovery = false;

	let start_position = matches.opt_str("start-position")
		.unwrap_or("0".to_string())
		.parse().unwrap_or(0.0);

	let session_config = {
		let device_id = librespot::core::session::device_id(&name);

		SessionConfig {
			user_agent: VERSION.to_string(),
			device_id: device_id
		}
	};

	let player_config = {
		PlayerConfig {
			bitrate: Bitrate::Bitrate320,
			onstart: matches.opt_str("onstart"),
			onstop: matches.opt_str("onstop"),
		}
	};

	let connect_config = {
		ConnectConfig {
			name: name,
			device_type: DeviceType::default(),
		}
	};

	Setup {
		cache: cache,
		session_config: session_config,
		player_config: player_config,
		connect_config: connect_config,
		credentials: credentials,
		authenticate: authenticate,
		enable_discovery: enable_discovery,

		get_token: matches.opt_present("get-token"),
		client_id: matches.opt_str("client-id"),
		scope: matches.opt_str("scope"),

		single_track: matches.opt_str("single-track"),
		start_position: (start_position * 1000.0) as u32,
	}
}

struct Main {
	cache: Option<Cache>,
	session_config: SessionConfig,
	player_config: PlayerConfig,
	connect_config: ConnectConfig,
	handle: Handle,

#[cfg(not(target_os="windows"))]
	discovery: Option<DiscoveryStream>,
#[cfg(target_os="windows")]
	discovery: Option<String>,
	signal: IoStream<()>,

	spirc: Option<Spirc>,
	spirc_task: Option<SpircTask>,
	connect: Box<Future<Item=Session, Error=io::Error>>,
	connect_state: Async<librespot::core::session::Session>,

	player: Option<Player>,

	shutdown: bool,
	authenticate: bool
}

impl Main {
	fn new(handle: Handle, setup: Setup) -> Main {
		let mut task = Main {
			handle: handle.clone(),
			cache: setup.cache,
			session_config: setup.session_config,
			player_config: setup.player_config,
			connect_config: setup.connect_config,

			connect: Box::new(futures::future::empty()),
			connect_state: Async::NotReady,
			discovery: None,
			spirc: None,
			spirc_task: None,

			player: None,

			shutdown: false,
			authenticate: setup.authenticate,
			signal: tokio_signal::ctrl_c(&handle).flatten_stream().boxed()
		};

		if setup.enable_discovery {
			let config = task.connect_config.clone();
			let device_id = task.session_config.device_id.clone();

			task.discovery = Some(discovery(&handle, config, device_id).unwrap());
		}

		if let Some(credentials) = setup.credentials {
			task.credentials(credentials);
		}

		task
	}

	fn credentials(&mut self, credentials: Credentials) {
		let config = self.session_config.clone();
		let handle = self.handle.clone();

		let connection = Session::connect(config, credentials, self.cache.clone(), handle);

		self.connect = connection;
		self.spirc = None;
		let task = mem::replace(&mut self.spirc_task, None);
		if let Some(task) = task {
			self.handle.spawn(task);
		}
	}
}

impl Future for Main {
	type Item = ();
	type Error = ();

	fn poll(&mut self) -> Poll<(), ()> {
		loop {
			let mut progress = false;

#[cfg(not(target_os="windows"))] {
			if let Some(Async::Ready(Some(creds))) = self.discovery.as_mut().map(|d| d.poll().unwrap()) {
				if let Some(ref spirc) = self.spirc {
					spirc.shutdown();
				}
				self.credentials(creds);

				progress = true;
			}
}

			if let Async::NotReady = self.connect_state {
				self.connect_state = self.connect.poll().unwrap();
			}

			if let Async::Ready(ref session) = self.connect_state {
				if self.authenticate {
					if !self.shutdown {
						if let Some(ref spirc) = self.spirc {
							spirc.shutdown();
						}
						self.shutdown = true;
					} else {
						return Ok(Async::Ready(()));
					}
				}
				else {
					self.connect = Box::new(futures::future::empty());
					let player_config = self.player_config.clone();
					let connect_config = self.connect_config.clone();

					let mixer = (mixer::find(Some("softvol")).unwrap())();

					let audio_filter = mixer.get_audio_filter();
					let backend = audio_backend::find(None).unwrap();
					let player = Player::new(player_config, session.clone(), audio_filter, move || {
						(backend)(None)
					});

					self.player = Some(player.clone());

					let (spirc, spirc_task) = Spirc::new(connect_config, session.clone(), player, mixer);
					self.spirc = Some(spirc);
					self.spirc_task = Some(spirc_task);
				}

				progress = true;
			}

			if let Async::Ready(Some(())) = self.signal.poll().unwrap() {
				if !self.shutdown {
					if let Some(ref spirc) = self.spirc {
						spirc.shutdown();
					}
					self.shutdown = true;
				} else {
					return Ok(Async::Ready(()));
				}

				progress = true;
			}

			if let Some(ref mut spirc_task) = self.spirc_task {
				if let Async::Ready(()) = spirc_task.poll().unwrap() {
					if self.shutdown {
						return Ok(Async::Ready(()));
					} else {
						panic!("Spirc shut down unexpectedly");
					}
				}
			}

			if !progress {
				return Ok(Async::NotReady);
			}
		}
	}
}

fn main() {
	let mut core = Core::new().unwrap();
	let handle = core.handle();

	let args: Vec<String> = std::env::args().collect();
	let Setup { cache, session_config, player_config, connect_config, credentials, authenticate, enable_discovery, get_token, client_id, scope, single_track, start_position } = setup(&args.clone());

	if let Some(ref track_id) = single_track {
		match credentials {
			Some(credentials) => {
				let backend = audio_backend::find(None).unwrap();

				let track = SpotifyId::from_base62(
									track_id.replace("spotty://", "")
									.replace("spotify://", "")
									.replace("spotify:", "")
									.replace("track:", "")
									.as_str());

				let session = core.run(Session::connect(session_config.clone(), credentials, cache.clone(), handle)).unwrap();

				let player = Player::new(player_config, session.clone(), None, move || (backend)(None));

				core.run(player.load(track, true, start_position)).unwrap();
			}
			None => {
				println!("Missing credentials");
			}
		}
	}
	else if authenticate && !enable_discovery {
		core.run(Session::connect(session_config.clone(), credentials.unwrap(), cache.clone(), handle)).unwrap();
		println!("authorized");
	}
	else if get_token {
		if let Some(client_id) = client_id {
			let session = core.run(Session::connect(session_config, credentials.unwrap(), cache.clone(), handle)).unwrap();
			let scope = scope.unwrap_or("user-read-private,playlist-read-private,playlist-read-collaborative,playlist-modify-public,playlist-modify-private,user-follow-modify,user-follow-read,user-library-read,user-library-modify,user-top-read,user-read-recently-played".to_string());
			let url = format!("hm://keymaster/token/authenticated?client_id={}&scope={}", client_id, scope);

			let result = core.run(session.mercury().get(url).map(move |response| {
				let data = response.payload.first().expect("Empty payload");
				let token = String::from_utf8(data.clone()).unwrap();
				println!("{}", token);
			}).boxed());

			match result {
				Ok(_) => (),
				Err(e) => println!("error getting token {:?}", e),
			}
		}
		else {
			println!("Use --client-id to provide a CLIENT_ID");
		}
	}
	else {
		core.run(Main::new(handle, Setup { cache, session_config, player_config, connect_config, credentials, authenticate, enable_discovery, get_token, client_id, scope, single_track, start_position })).unwrap()
	}
}

<|endoftext|>


<commit_before>fn main(expr: &str) -> i32 {
  let mut result = 0;
  let mut stack:Vec<i32> = Vec::new();
  for token in expr.split_whitespace() {
    let wrapped_operand = token.parse::<i32>();
    let is_operator = wrapped_operand.is_err();
    if is_operator {
      if stack.len() < 2 {
        panic!("Unsufficient operands before operator");
      }
      // xxxFlorent: Any way to destructure like this? Not sure of what I am doing below
      // let [ operand1, operand2 ] = stack.drain((token.len() - 3)..).collect();
      let operand2 = stack.pop().expect("expected i32 values only in stack");
      let operand1 = stack.pop().expect("expected i32 values only in stack");
      result += match token {
        "+" => operand1 + operand2,
        "-" => operand1 - operand2,
        "*" => operand1 * operand2,
        _ => panic!("Unsupported operator")
      }
    } else {
      stack.push(wrapped_operand.unwrap());
    }
  }

  if stack.len() > 0 {
    panic!("Remaining untreated operands. Probably missing operator.");
  }
  return result;
}

#[test]
fn it_adds() {
  let result = main("1 2 +");
  assert_eq!(result, 3);
}

#[test]
fn it_substracts() {
  let result = main("1 2 -");
  assert_eq!(result, -1);
}

#[test]
fn it_multiplies() {
  let result = main("6 7 *");
  assert_eq!(result, 42);
}

#[test]
#[should_panic]
fn it_panics_for_unsupported_operators() {
  main("1 2 =");
  // xxxFlorent: How to test the panic message is right?
}

#[test]
#[should_panic]
fn it_panics_for_unsufficient_operands() {
  main("1 +");
  // xxxFlorent: How to test the panic message is right?
}

#[test]
#[should_panic]
fn it_panics_for_unsufficient_operators() {
  main("1 2 3 +");
  // xxxFlorent: How to test the panic message is right?
}
<commit_msg>Support divisions and float operands<commit_after>fn main(expr: &str) -> f32 {
  let mut result = 0.0;
  let mut stack:Vec<f32> = Vec::new();
  for token in expr.split_whitespace() {
    let wrapped_operand = token.parse::<f32>();
    let is_operator = wrapped_operand.is_err();
    if is_operator {
      if stack.len() < 2 {
        panic!("Unsufficient operands before operator");
      }
      // xxxFlorent: Any way to destructure like this? Not sure of what I am doing below
      // let [ operand1, operand2 ] = stack.drain((token.len() - 3)..).collect();
      let operand2 = stack.pop().expect("expected f32 values only in stack");
      let operand1 = stack.pop().expect("expected f32 values only in stack");
      result += match token {
        "+" => operand1 + operand2,
        "-" => operand1 - operand2,
        "*" => operand1 * operand2,
        "/" => operand1 / operand2,
        _ => panic!("Unsupported operator")
      }
    } else {
      stack.push(wrapped_operand.unwrap());
    }
  }

  if stack.len() > 0 {
    panic!("Remaining untreated operands. Probably missing operator.");
  }
  return result;
}

#[test]
fn it_adds() {
  let result = main("1 2 +");
  assert_eq!(result, 3.0);
}

#[test]
fn it_substracts() {
  let result = main("1 2 -");
  assert_eq!(result, -1.0);
}

#[test]
fn it_multiplies() {
  let result = main("6 7 *");
  assert_eq!(result, 42.0);
}

#[test]
fn it_divides() {
  let result = main("1 2 /");
  assert_eq!(result, 0.5);
}

#[test]
#[should_panic]
fn it_panics_for_unsupported_operators() {
  main("1 2 =");
  // xxxFlorent: How to test the panic message is right?
}

#[test]
#[should_panic]
fn it_panics_for_unsufficient_operands() {
  main("1 +");
  // xxxFlorent: How to test the panic message is right?
}

#[test]
#[should_panic]
fn it_panics_for_unsufficient_operators() {
  main("1 2 3 +");
  // xxxFlorent: How to test the panic message is right?
}
<|endoftext|>


<commit_before>use instr::Instr;
use cpu::Cpu;
use time::precise_time_ns;

extern crate time;

mod instr;
mod cpu;

pub struct AddressSpace {
    data: [u8; 0xFFFF],
}

impl AddressSpace {

    pub fn new() -> AddressSpace {
        AddressSpace { data: [0; 0xFFFF] }
    }

    pub fn read(&self, addr: u16) -> u8 {
        self.data[addr as usize]
    }

    pub fn read_u16(&self, addr: u16) -> u16 {
        self.data[addr as usize] as u16 | ((self.data[addr as usize + 1] as u16) << 8)
    }

    pub fn read_slice(&self, addr: u16, bytes: u16) -> &[u8] {
        &self.data[addr as usize .. (addr + bytes) as usize]
    }

    pub fn write(&mut self, addr: u16, data: u8) {
        self.data[addr as usize] = data;
    }

    pub fn write_u16(&mut self, addr: u16, data: u16) {
        let lo = (data & 0xFF) as u8;
        let hi = ((data & 0xFF00) >> 8) as u8;
        self.data[addr as usize] = lo;
        self.data[addr as usize + 1] = hi;
    }

}

#[derive(Copy, Clone)]
pub enum RegFlag {
    Zero,
    Subtract,
    HalfCarry,
    Carry,
}

#[derive(Copy, Clone)]
pub enum Register {
    A,
    B,
    C,
    D,
    E,
    F,
    H,
    L,
    AF,
    BC,
    DE,
    HL,
    SP,
    PC,
    Flag,
}

pub struct RegData {
    a: u8,
    b: u8,
    c: u8,
    d: u8,
    e: u8,
    f: u8,
    h: u8,
    l: u8,
    sp: u16,
    pc: u16,
    flag: u8,
}

impl RegData {

    pub fn new() -> RegData {
        RegData {
            a: 0,
            b: 0,
            c: 0,
            d: 0,
            e: 0,
            f: 0,
            h: 0,
            l: 0,
            sp: 0xFFFE,
            pc: 0x100,
            flag: 0,
        }
    }

    pub fn read(&self, reg: Register) -> u8 {
        match reg {
            Register::A => self.a,
            Register::B => self.b,
            Register::C => self.c,
            Register::D => self.d,
            Register::E => self.e,
            Register::F => self.f,
            Register::H => self.h,
            Register::L => self.l,
            Register::Flag => self.flag,
            _ => panic!("Register not available for 8-bit read"),
        }
    }

    pub fn read_u16(&self, reg: Register) -> u16 {
        match reg {
            Register::AF => (self.a as u16) << 8 | self.f as u16,
            Register::BC => (self.b as u16) << 8 | self.c as u16,
            Register::DE => (self.d as u16) << 8 | self.e as u16,
            Register::HL => (self.h as u16) << 8 | self.l as u16,
            Register::SP => self.sp,
            Register::PC => self.pc,
            _ => panic!("Register not available for 16-bit read"),
        }
    }

    pub fn write(&mut self, reg: Register, data: u8) {
        match reg {
            Register::A => self.a = data,
            Register::B => self.b = data,
            Register::C => self.c = data,
            Register::D => self.d = data,
            Register::E => self.e = data,
            Register::F => self.f = data,
            Register::H => self.h = data,
            Register::L => self.l = data,
            _ => panic!("Register not available for 8-bit write"),
        }
    }

    pub fn write_u16(&mut self, reg: Register, data: u16) {
        let (hi, lo) = ((data & 0xFF00 >> 8) as u8, (data & 0xFF) as u8);
        match reg {
            Register::AF => {
                self.a = hi;
                self.f = lo;
            },
            Register::BC => {
                self.b = hi;
                self.c = lo;
            },
            Register::DE => {
                self.d = hi;
                self.c = lo;
            },
            Register::HL => {
                self.h = hi;
                self.l = lo;
            },
            Register::SP => self.sp = data,
            Register::PC => self.pc = data,
            _ => panic!("Register not available for 16-bit write"),
        }
    }

    pub fn copy(&mut self, dst: Register, src: Register) {
        let data = self.read(src);
        self.write(dst, data);
    }

    pub fn copy_u16(&mut self, dst: Register, src: Register) {
        let data = self.read_u16(src);
        self.write_u16(dst, data);
    }

    pub fn set_flag(&mut self, flag: RegFlag, on: bool) {
        let bit = match flag {
            RegFlag::Zero => 0x80,
            RegFlag::Subtract => 0x40,
            RegFlag::HalfCarry => 0x20,
            RegFlag::Carry => 0x10,
        };
        if (on) {
            self.flag |= bit;
        } else {
            self.flag &= bit ^ 0xFF;
        }
    }

    pub fn get_flag(&self, flag: RegFlag) -> bool {
        let bit = match flag {
            RegFlag::Zero => 0x80,
            RegFlag::Subtract => 0x40,
            RegFlag::HalfCarry => 0x20,
            RegFlag::Carry => 0x10,
        };
        self.flag & bit != 0
    }

    pub fn advance_pc(&mut self) -> u16 {
        let pc = self.pc;
        self.pc += 1;
        pc
    }

    pub fn set_pc(&mut self, addr: u16) -> u16 {
        let pc = self.pc;
        self.pc = addr;
        pc
    }

    pub fn add_pc(&mut self, n: i8) -> u16 {
        let pc = self.pc;
        self.pc = ((self.pc as i32) + (n as i32)) as u16;
        pc
    }

}

fn main() {
    let cpu = Cpu::new();
    'main: loop {
        println!("Nothing to do, breaking out of main");
        break 'main;
    }
}
<commit_msg>Implement basic rom loading function<commit_after>use instr::Instr;
use cpu::Cpu;
use time::precise_time_ns;
use std::fs::File;
use std::io::Read;

extern crate time;

mod instr;
mod cpu;

pub struct AddressSpace {
    data: [u8; 0xFFFF],
}

impl AddressSpace {

    pub fn new() -> AddressSpace {
        AddressSpace { data: [0; 0xFFFF] }
    }

    pub fn read(&self, addr: u16) -> u8 {
        self.data[addr as usize]
    }

    pub fn read_u16(&self, addr: u16) -> u16 {
        self.data[addr as usize] as u16 | ((self.data[addr as usize + 1] as u16) << 8)
    }

    pub fn read_slice(&self, addr: u16, bytes: u16) -> &[u8] {
        &self.data[addr as usize .. (addr + bytes) as usize]
    }

    pub fn write(&mut self, addr: u16, data: u8) {
        self.data[addr as usize] = data;
    }

    pub fn write_u16(&mut self, addr: u16, data: u16) {
        let lo = (data & 0xFF) as u8;
        let hi = ((data & 0xFF00) >> 8) as u8;
        self.data[addr as usize] = lo;
        self.data[addr as usize + 1] = hi;
    }

    pub fn load_rom(&mut self, rom: &mut File) -> std::io::Result<()> {
        // Read in header first
        try!(rom.read(&mut self.data[0x000..0x150]));
        // Then read in remaining cart data
        try!(rom.read(&mut self.data[0x0150..0x8000]));
        Ok(())
    }

}

#[derive(Copy, Clone)]
pub enum RegFlag {
    Zero,
    Subtract,
    HalfCarry,
    Carry,
}

#[derive(Copy, Clone)]
pub enum Register {
    A,
    B,
    C,
    D,
    E,
    F,
    H,
    L,
    AF,
    BC,
    DE,
    HL,
    SP,
    PC,
    Flag,
}

pub struct RegData {
    a: u8,
    b: u8,
    c: u8,
    d: u8,
    e: u8,
    f: u8,
    h: u8,
    l: u8,
    sp: u16,
    pc: u16,
    flag: u8,
}

impl RegData {

    pub fn new() -> RegData {
        RegData {
            a: 0,
            b: 0,
            c: 0,
            d: 0,
            e: 0,
            f: 0,
            h: 0,
            l: 0,
            sp: 0xFFFE,
            pc: 0x100,
            flag: 0,
        }
    }

    pub fn read(&self, reg: Register) -> u8 {
        match reg {
            Register::A => self.a,
            Register::B => self.b,
            Register::C => self.c,
            Register::D => self.d,
            Register::E => self.e,
            Register::F => self.f,
            Register::H => self.h,
            Register::L => self.l,
            Register::Flag => self.flag,
            _ => panic!("Register not available for 8-bit read"),
        }
    }

    pub fn read_u16(&self, reg: Register) -> u16 {
        match reg {
            Register::AF => (self.a as u16) << 8 | self.f as u16,
            Register::BC => (self.b as u16) << 8 | self.c as u16,
            Register::DE => (self.d as u16) << 8 | self.e as u16,
            Register::HL => (self.h as u16) << 8 | self.l as u16,
            Register::SP => self.sp,
            Register::PC => self.pc,
            _ => panic!("Register not available for 16-bit read"),
        }
    }

    pub fn write(&mut self, reg: Register, data: u8) {
        match reg {
            Register::A => self.a = data,
            Register::B => self.b = data,
            Register::C => self.c = data,
            Register::D => self.d = data,
            Register::E => self.e = data,
            Register::F => self.f = data,
            Register::H => self.h = data,
            Register::L => self.l = data,
            _ => panic!("Register not available for 8-bit write"),
        }
    }

    pub fn write_u16(&mut self, reg: Register, data: u16) {
        let (hi, lo) = ((data & 0xFF00 >> 8) as u8, (data & 0xFF) as u8);
        match reg {
            Register::AF => {
                self.a = hi;
                self.f = lo;
            },
            Register::BC => {
                self.b = hi;
                self.c = lo;
            },
            Register::DE => {
                self.d = hi;
                self.c = lo;
            },
            Register::HL => {
                self.h = hi;
                self.l = lo;
            },
            Register::SP => self.sp = data,
            Register::PC => self.pc = data,
            _ => panic!("Register not available for 16-bit write"),
        }
    }

    pub fn copy(&mut self, dst: Register, src: Register) {
        let data = self.read(src);
        self.write(dst, data);
    }

    pub fn copy_u16(&mut self, dst: Register, src: Register) {
        let data = self.read_u16(src);
        self.write_u16(dst, data);
    }

    pub fn set_flag(&mut self, flag: RegFlag, on: bool) {
        let bit = match flag {
            RegFlag::Zero => 0x80,
            RegFlag::Subtract => 0x40,
            RegFlag::HalfCarry => 0x20,
            RegFlag::Carry => 0x10,
        };
        if (on) {
            self.flag |= bit;
        } else {
            self.flag &= bit ^ 0xFF;
        }
    }

    pub fn get_flag(&self, flag: RegFlag) -> bool {
        let bit = match flag {
            RegFlag::Zero => 0x80,
            RegFlag::Subtract => 0x40,
            RegFlag::HalfCarry => 0x20,
            RegFlag::Carry => 0x10,
        };
        self.flag & bit != 0
    }

    pub fn advance_pc(&mut self) -> u16 {
        let pc = self.pc;
        self.pc += 1;
        pc
    }

    pub fn set_pc(&mut self, addr: u16) -> u16 {
        let pc = self.pc;
        self.pc = addr;
        pc
    }

    pub fn add_pc(&mut self, n: i8) -> u16 {
        let pc = self.pc;
        self.pc = ((self.pc as i32) + (n as i32)) as u16;
        pc
    }

}

fn main() {
    let cpu = Cpu::new();
    'main: loop {
        println!("Nothing to do, breaking out of main");
        break 'main;
    }
}
<|endoftext|>


<commit_before>//! Implementation of a simple uTP client and server.
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate getopts;
extern crate daemonize;
extern crate udt;

use daemonize::{Daemonize};
use std::process;
use std::process::Command;
use std::thread;
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
use std::net;
use std::str;
use std::env;
use std::fs::File;
use std::str::FromStr;
use std::path::Path;
use getopts::Options;
use udt::*;

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options] REMOTE-LOCATION", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    use std::io::{stdin, stdout, stderr, Read, Write};

    // This example may run in either server or client mode.
    // Using an enum tends to make the code cleaner and easier to read.
    enum Mode {Server, Client}

    // Start logging
    env_logger::init().expect("Error starting logger");

    // Fetch arguments
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optopt("o", "output", "set output file name", "NAME");
    opts.optflag("s", "server", "server mode");
    opts.optflag("p", "port-range", "server listening port range");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }

    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };

    // Parse the mode argument
    let mode: Mode = match matches.opt_present("s") {
        true => Mode::Server,
        false => Mode::Client
    };

    match mode {
        Mode::Server => {
            udt::init();
            let sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Stream).unwrap();
            sock.setsockopt(UdtOpts::UDP_RCVBUF, 5590000i32);
            sock.setsockopt(UdtOpts::UDP_SNDBUF, 5590000i32);
            sock.bind(SocketAddr::V4(SocketAddrV4::from_str("0.0.0.0:55000").unwrap())).unwrap();
            let my_addr = sock.getsockname().unwrap();
            println!("Server bound to {:?}", my_addr);

            sock.listen(5).unwrap();

            let (mut stream, peer) = sock.accept().unwrap();
            println!("Received new connection from peer {:?}", peer);

            let mut f = File::open(input).unwrap();

            let daemonize = Daemonize::new();

            let mut writer = stdout();
            // let _ = writeln!(&mut stderr(), "Serving on {}", addr);

            let mut startmagic = vec![0; 1];
            let amount_read = stream.recv(&mut startmagic, 1).unwrap();
            println!("got {} magic byte(s).", amount_read);

            // match daemonize.start() {
            //     Ok(_) => { let _ = writeln!(&mut stderr(), "daemonized"); }
            //     Err(e) => { let _ = writeln!(&mut stderr(), "RWRWARWARARRR"); }
            // }

            let mut total = 0;
            // Create a reasonably sized buffer
            let mut payload = vec![0; 1300];
            // loop {
            //     match stream.send(&payload) {
            //         Ok(written) => { print!("."); }
            //         Err(e) => { panic!("{:?}", e); }
            //     }
            // }
            loop {
                match f.read(&mut payload) {
                    Ok(read) => {
                        match stream.send(&payload[0..read]) {
                            Ok(0) => {
                                println!("EOF.");
                                break;
                            }
                            Ok(written) => {
                                total += written;
                                print!("\rwritten {}", total);
                            },
                            Err(e) => {
                                stream.close().expect("Error closing stream");
                                panic!("{:?}", e);
                            }
                        }
                    },
                    Err(e) => {
                        stream.close().expect("Error closing stream");
                        panic!("{}", e);
                    }
                }
            }
            stream.close().expect("Error closing stream.");
            println!("yay");
        }
        Mode::Client => {
            let sections: Vec<&str> = input.split(":").collect();
            let addr: String = sections[0].to_owned();
            let path: String = sections[1].to_owned();
            let cmd = format!("~/bin/shoop -s {}", path);
            println!("addr: {}, path: {}, cmd: {}", addr, path, cmd);

            // let output = Command::new("ssh")
            //                      .arg(addr.to_owned())
            //                      .arg(cmd)
            //                      .output()
            //                      .unwrap_or_else(|e| {
            //                          panic!("failed to execute process: {}", e);
            //                      });
            // let udp_addr = String::from_utf8_lossy(&output.stdout).trim().to_owned();
            //
            // // Create a stream and try to connect to the remote address
            // println!("shoop server told us to connect to {}", udp_addr);
            udt::init();
            let sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Stream).unwrap();
            sock.setsockopt(UdtOpts::UDP_RCVBUF, 5590000i32);
            sock.setsockopt(UdtOpts::UDP_SNDBUF, 5590000i32);
            let addr: SocketAddr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from_str(&addr).unwrap(), 55000));
            sock.bind(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from_str("0.0.0.0").unwrap(), 0)));
            match sock.connect(addr) {
                Ok(()) => {
                    println!("connected!");
                },
                Err(e) => {
                    panic!("errrrrrrr {:?}", e);
                }
            }

            let mut f = File::create("outfile").unwrap();
            println!("created file.");
            let mut payload = vec![0; 1024 * 1024];
            sock.send(b"\x01");
            println!("write magic byte.");

            let mut total = 0;
            loop {
                match sock.recv(&mut payload, 1024 * 1024) {
                    Ok(0) => {
                        println!("EOF");
                        break
                    },
                    Ok(read) => {
                        total += read;
                        println!("read {}", total);
                        f.write_all(&payload[0..(read-1) as usize]);
                    },
                    Err(e) => {
                        panic!("{:?}", e);
                    }
                }
            }
            sock.close().expect("Error closing socket.");
        }
    }
}

<commit_msg>try to make server chill the fuck out for a second<commit_after>//! Implementation of a simple uTP client and server.
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate getopts;
extern crate daemonize;
extern crate udt;

use daemonize::{Daemonize};
use std::process;
use std::process::Command;
use std::thread;
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
use std::net;
use std::str;
use std::env;
use std::fs::File;
use std::str::FromStr;
use std::path::Path;
use getopts::Options;
use udt::*;

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options] REMOTE-LOCATION", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    use std::io::{stdin, stdout, stderr, Read, Write};

    // This example may run in either server or client mode.
    // Using an enum tends to make the code cleaner and easier to read.
    enum Mode {Server, Client}

    // Start logging
    env_logger::init().expect("Error starting logger");

    // Fetch arguments
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optopt("o", "output", "set output file name", "NAME");
    opts.optflag("s", "server", "server mode");
    opts.optflag("p", "port-range", "server listening port range");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }

    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };

    // Parse the mode argument
    let mode: Mode = match matches.opt_present("s") {
        true => Mode::Server,
        false => Mode::Client
    };

    match mode {
        Mode::Server => {
            udt::init();
            let sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Stream).unwrap();
            sock.setsockopt(UdtOpts::UDP_RCVBUF, 5590000i32);
            sock.setsockopt(UdtOpts::UDP_SNDBUF, 5590000i32);
            sock.setsockopt(UdtOpts::UDT_SNDSYN, true);
            sock.bind(SocketAddr::V4(SocketAddrV4::from_str("0.0.0.0:55000").unwrap())).unwrap();
            let my_addr = sock.getsockname().unwrap();
            println!("Server bound to {:?}", my_addr);

            sock.listen(1).unwrap();

            let (mut stream, peer) = sock.accept().unwrap();
            println!("Received new connection from peer {:?}", peer);

            let mut f = File::open(input).unwrap();

            let daemonize = Daemonize::new();

            let mut writer = stdout();

            let mut startmagic = vec![0; 1];
            let amount_read = stream.recv(&mut startmagic, 1).unwrap();
            println!("got {} magic byte(s).", amount_read);

            // match daemonize.start() {
            //     Ok(_) => { let _ = writeln!(&mut stderr(), "daemonized"); }
            //     Err(e) => { let _ = writeln!(&mut stderr(), "RWRWARWARARRR"); }
            // }

            let mut total = 0;
            let mut payload = vec![0; 1300];
            loop {
                match f.read(&mut payload) {
                    Ok(read) => {
                        match stream.send(&payload[0..read]) {
                            Ok(0) => {
                                println!("EOF.");
                                break;
                            }
                            Ok(written) => {
                                total += written;
                                print!("\rwritten {}", total);
                            },
                            Err(e) => {
                                stream.close().expect("Error closing stream");
                                panic!("{:?}", e);
                            }
                        }
                    },
                    Err(e) => {
                        stream.close().expect("Error closing stream");
                        panic!("{}", e);
                    }
                }
            }
            stream.close().expect("Error closing stream.");
            println!("yay");
        }
        Mode::Client => {
            let sections: Vec<&str> = input.split(":").collect();
            let addr: String = sections[0].to_owned();
            let path: String = sections[1].to_owned();
            let cmd = format!("~/bin/shoop -s {}", path);
            println!("addr: {}, path: {}, cmd: {}", addr, path, cmd);

            // let output = Command::new("ssh")
            //                      .arg(addr.to_owned())
            //                      .arg(cmd)
            //                      .output()
            //                      .unwrap_or_else(|e| {
            //                          panic!("failed to execute process: {}", e);
            //                      });
            // let udp_addr = String::from_utf8_lossy(&output.stdout).trim().to_owned();
            //
            // // Create a stream and try to connect to the remote address
            // println!("shoop server told us to connect to {}", udp_addr);
            udt::init();
            let sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Stream).unwrap();
            sock.setsockopt(UdtOpts::UDP_RCVBUF, 5590000i32);
            sock.setsockopt(UdtOpts::UDP_SNDBUF, 5590000i32);
            let addr: SocketAddr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from_str(&addr).unwrap(), 55000));
            sock.bind(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from_str("0.0.0.0").unwrap(), 0)));
            match sock.connect(addr) {
                Ok(()) => {
                    println!("connected!");
                },
                Err(e) => {
                    panic!("errrrrrrr {:?}", e);
                }
            }

            let mut f = File::create("outfile").unwrap();
            println!("created file.");
            let mut payload = vec![0; 1024 * 1024];
            sock.send(b"\x01");
            println!("write magic byte.");

            let mut total = 0;
            loop {
                match sock.recv(&mut payload, 1024 * 1024) {
                    Ok(0) => {
                        println!("EOF");
                        break
                    },
                    Ok(read) => {
                        total += read;
                        println!("read {}", total);
                        f.write_all(&payload[0..(read) as usize]);
                    },
                    Err(e) => {
                        panic!("{:?}", e);
                    }
                }
            }
            sock.close().expect("Error closing socket.");
        }
    }
}

<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>It parses to an object.<commit_after>#![feature(drain)]
use std::rc::Rc;
use std::cell::{RefCell, RefMut};

type S = Rc<RefCell<Rc<State>>>;
#[derive(Debug)]
enum State {
    Any {
        next: S,
    },
    Lit {
        val: String,
        next: S,
    },
    Split {
        one: S,
        two: S,
    },
    Match
}

#[derive(Debug)]
struct Fragment {
    tips: Vec<S>,
    state: S
}

impl State {
    fn tip() -> S {
        Rc::new(RefCell::new(Rc::new(State::Match)))
    }
    /*
    fn patch_on(self, f: Fragment) -> Fragment {
        use Fragment::*;

        Rc::new(match self {
            Any { next: None } => Any { next: Some(f) },
            Any { next: Some(frag) } => Any { next: Some(frag.patch_on(f)) },

            Lit { val, next: None } => Lit { val: val, next: Some(f) },
            Lit { val, next: Some(frag) } => Lit { val: val, next: Some(frag.patch_on(f)) },

            Split { next: None } => Split { next: Some((f.clone(), f)) },
            Split { next: Some((a, b)) } => Split {
                next: Some(
                    (a.patch_on(f.clone()), b.patch_on(f))
                )
            }
        })
    }
    */
}

impl Fragment {
    fn patch(mut self, f: Fragment) -> Fragment {
        for t in self.tips.drain(..) {
            *t.borrow_mut() = f.state.borrow().clone();
        }
        self.tips = f.tips;
        self
    }

    fn new(s: State) -> Fragment {
        use State::*;

        let tips = match s {
            Any { ref next } => vec![next.clone()],
            Lit { ref next, .. } => vec![next.clone()],
            Split { ref one, ref two } => vec![one.clone(), two.clone()],
            Match => Vec::new()
        };

        Fragment {
            tips: tips,
            state: Rc::new(RefCell::new(Rc::new(s)))
        }
    }
}

fn main() {
    let re = "ab.a.";
    let mut fragments: Vec<Fragment> = Vec::new();
    for ch in re.chars() {
        let newfrag = match ch {
            '.' => {
                let e2 = fragments.pop().expect("Found . without a previous fragment");
                let e1 = fragments.pop().expect("Found . without two previous fragment");
                e1.patch(e2)
            },
            '+' => {
                let e = fragments.pop().expect("Found + without a previous fragment");
                let s = e.state.clone();
                e.patch(Fragment::new(State::Split {
                    one: s,
                    two: State::tip()
                }))
            },
            a => {
                Fragment::new(State::Lit {
                    val: format!("{}", a),
                    next: State::tip()
                })
            }
        };
        fragments.push(newfrag);
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::fs::File;
use std::process;
use std::env;
use system_services::SystemInterface;
mod configuration;
mod provisioner;
mod logger;
mod file;
mod system_services;
mod platform;

fn main() {
    println!("sokan");
    let mut filename = "default.yaml".to_string();

    if env::args().len() > 1 {
        let mut args_iterator = env::args().skip(1);
        filename = args_iterator.next().unwrap().to_string();
    }

    let mut file_result :std::fs::File;
    match File::open(&filename) {
        Ok(result) => file_result = result,
        Err(error) => {
            println!("Error occured while accessing {}: {:?}", filename, error);
            return;
        }
    }

    let mut yaml_file = String::new();
    match file_result.read_to_string(&mut yaml_file) {
        Err(error) => println!("Failed to read {} - {:?}", filename, error),
        _ => { }
    }

    let configuration = configuration::from_yaml(yaml_file.to_string());
    let service = system_services::SystemServices;
    let provisioner = provisioner::Provisioner::new(service.clone());

    let exit_code = match service.os_type() {
        system_services::OSType::Redhat  => provisioner.provision(&configuration),
        _                                => {
            logger::print_message("Unsupported platform".into(), logger::MessageType::Stderr);
            1
        }
    };

    process::exit(exit_code);
}
<commit_msg>exit if no argument was provided<commit_after>use std::io::prelude::*;
use std::fs::File;
use std::process;
use std::env;
use system_services::SystemInterface;
mod configuration;
mod provisioner;
mod logger;
mod file;
mod system_services;
mod platform;

fn main() {
    println!("sokan");
    let mut filename = "default.yaml".to_string();

    if env::args().len() < 2 {
        println!("No arguments provided");
        println!("Usage");
        println!("sokan <configuration_file>");
        process::exit(2);
    }
    let mut args_iterator = env::args().skip(1);
    filename = args_iterator.next().unwrap().to_string();

    let mut file_result :std::fs::File;
    match File::open(&filename) {
        Ok(result) => file_result = result,
        Err(error) => {
            println!("Error occured while accessing {}: {:?}", filename, error);
            return;
        }
    }

    let mut yaml_file = String::new();
    match file_result.read_to_string(&mut yaml_file) {
        Err(error) => println!("Failed to read {} - {:?}", filename, error),
        _ => { }
    }

    let configuration = configuration::from_yaml(yaml_file.to_string());
    let service = system_services::SystemServices;
    let provisioner = provisioner::Provisioner::new(service.clone());

    let exit_code = match service.os_type() {
        system_services::OSType::Redhat  => provisioner.provision(&configuration),
        _                                => {
            logger::print_message("Unsupported platform".into(), logger::MessageType::Stderr);
            1
        }
    };

    process::exit(exit_code);
}
<|endoftext|>


<commit_before>#[macro_use] extern crate log;
extern crate env_logger;
#[macro_use] extern crate futures;
#[macro_use] extern crate tokio_core;

use std::env;
use std::io::{self, Read, Write};
use std::net::SocketAddr;

use futures::{Future, Poll};
use futures::stream::Stream;
use tokio_core::reactor::Core;
use tokio_core::net::{TcpListener, TcpStream};

#[derive(Debug)]
enum ConnectionState {
    ClientReading,
    ClientWriting,
    ServerReading,
    ServerWriting,
}

#[must_use = "must use pipe"]
struct Pipe {
    client_addr: SocketAddr,
    server_addr: SocketAddr,
    client: TcpStream,
    server: TcpStream,
    state: ConnectionState,

    /// The buffer from the client to send to the server
    send_buf: Vec<u8>,

    /// The buffer from the server to send to the client
    recv_buf: Vec<u8>,
}

impl Future for Pipe {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(), io::Error> {
        trace!("Polling...");

        loop {

            match self.state {
                ConnectionState::ClientReading => {
                    loop {
                        trace!("Reading from {}", self.client_addr);

                        // TODO should really be a VecDequeue in case we read more than once
                        let bytes = try_nb!(self.client.read_to_end(&mut self.send_buf));
                        trace!("Read {} bytes from {}", bytes, self.client_addr);

                        if bytes == 0 {
                            self.state = ConnectionState::ServerWriting;
                            trace!("State switched to {:?}", self.state);
                            break;
                        }
                    }
                }

                ConnectionState::ServerWriting => {
                    trace!("Writing to {}", self.server_addr);
                    try_nb!(self.server.write_all(&mut self.send_buf));
                    trace!("Wrote {} bytes to {}", self.send_buf.len(), self.server_addr);

                    self.server.shutdown(::std::net::Shutdown::Write).expect("Failed to shutdown writes for server socket");
                    self.state = ConnectionState::ServerReading;
                    trace!("State switched to {:?}", self.state);
                }

                ConnectionState::ServerReading => {
                    loop {
                        trace!("Reading from {}", self.server_addr);

                        let bytes = try_nb!(self.server.read_to_end(&mut self.recv_buf));
                        trace!("Read {} bytes from {}", bytes, self.server_addr);

                        if bytes == 0 {
                            self.state = ConnectionState::ClientWriting;
                            trace!("State switched to {:?}", self.state);
                            break;
                        }
                    }
                }

                ConnectionState::ClientWriting => {
                    trace!("Writing to {}", self.client_addr);
                    try_nb!(self.client.write_all(&mut self.recv_buf));
                    trace!("Wrote {} bytes to {}", self.recv_buf.len(), self.client_addr);

                    self.state = ConnectionState::ClientReading;
                    trace!("State switched to {:?}", self.state);
                }
            }
        }
    }
}

fn main() {
    env_logger::init().unwrap();

    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse::<SocketAddr>().unwrap();

    let backend = env::args().nth(2).unwrap_or("127.0.0.1:12345".to_string());
    let backend = backend.parse::<SocketAddr>().unwrap();

    // Create the event loop that will drive this server
    let mut lp = Core::new().unwrap();
    let handle = lp.handle();
    let h2 = handle.clone();

    let s = TcpListener::bind(&addr, &handle.clone());

    // Create a TCP listener which will listen for incoming connections
    let listener = lp.run(futures::done(s)).unwrap();

    info!("Listening on: {}", addr);

    let conn = listener.incoming().map(move |(socket, addr)| {
        debug!("Incoming connection on {}", addr);

        // FIXME move this into the spawn so it is not blocking the main thread?
        let connected = TcpStream::connect(&backend, &h2);

        connected.and_then(move |server| {
            Ok (
                Pipe {
                    client_addr: addr,
                    server_addr: backend,
                    client: socket,
                    server: server,
                    state: ConnectionState::ClientReading,
                    send_buf: Vec::new(),
                    recv_buf: Vec::new(),
                }
            )
        }).boxed()
    });

    let server = conn.for_each(|conn| {
        trace!("Connecting...");

        let done = conn.and_then(|conn| {
            trace!("Before polling...");

            conn.and_then(|_| {
                debug!("Done.");
                futures::finished(())
            })
        }).map_err(|e| { // spawn expects an error type of () and we are passing through io::Error
            error!("Error trying proxy - {}", e);
            ()
        });

        handle.spawn(done);

        Ok(())
    });

    lp.run(server).unwrap();
}
<commit_msg>Cleanup the futures composition a bit<commit_after>#[macro_use] extern crate log;
extern crate env_logger;
#[macro_use] extern crate futures;
#[macro_use] extern crate tokio_core;

use std::env;
use std::io::{self, Read, Write};
use std::net::SocketAddr;

use futures::{Future, Poll};
use futures::stream::Stream;
use tokio_core::reactor::Core;
use tokio_core::net::{TcpListener, TcpStream};

#[derive(Debug)]
enum ConnectionState {
    ClientReading,
    ClientWriting,
    ServerReading,
    ServerWriting,
}

#[must_use = "Must use Pipe"]
struct Pipe {
    client_addr: SocketAddr,
    server_addr: SocketAddr,
    client: TcpStream,
    server: TcpStream,
    state: ConnectionState,

    /// The buffer from the client to send to the server
    send_buf: Vec<u8>,

    /// The buffer from the server to send to the client
    recv_buf: Vec<u8>,
}

impl Future for Pipe {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(), io::Error> {
        trace!("Polling...");

        loop {

            match self.state {
                ConnectionState::ClientReading => {
                    loop {
                        trace!("Reading from {}", self.client_addr);

                        // TODO should really be a VecDequeue in case we read more than once
                        let bytes = try_nb!(self.client.read_to_end(&mut self.send_buf));
                        trace!("Read {} bytes from {}", bytes, self.client_addr);

                        if bytes == 0 {
                            self.state = ConnectionState::ServerWriting;
                            trace!("State switched to {:?}", self.state);
                            break;
                        }
                    }
                }

                ConnectionState::ServerWriting => {
                    trace!("Writing to {}", self.server_addr);
                    try_nb!(self.server.write_all(&mut self.send_buf));
                    trace!("Wrote {} bytes to {}", self.send_buf.len(), self.server_addr);

                    self.server.shutdown(::std::net::Shutdown::Write).expect("Failed to shutdown writes for server socket");
                    self.state = ConnectionState::ServerReading;
                    trace!("State switched to {:?}", self.state);
                }

                ConnectionState::ServerReading => {
                    loop {
                        trace!("Reading from {}", self.server_addr);

                        let bytes = try_nb!(self.server.read_to_end(&mut self.recv_buf));
                        trace!("Read {} bytes from {}", bytes, self.server_addr);

                        if bytes == 0 {
                            self.state = ConnectionState::ClientWriting;
                            trace!("State switched to {:?}", self.state);
                            break;
                        }
                    }
                }

                ConnectionState::ClientWriting => {
                    trace!("Writing to {}", self.client_addr);
                    try_nb!(self.client.write_all(&mut self.recv_buf));
                    trace!("Wrote {} bytes to {}", self.recv_buf.len(), self.client_addr);

                    self.state = ConnectionState::ClientReading;
                    trace!("State switched to {:?}", self.state);
                }
            }
        }
    }
}

fn main() {
    env_logger::init().unwrap();

    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse::<SocketAddr>().unwrap();

    let backend = env::args().nth(2).unwrap_or("127.0.0.1:12345".to_string());
    let backend = backend.parse::<SocketAddr>().unwrap();

    // Create the event loop that will drive this server
    let mut lp = Core::new().unwrap();
    let handle = lp.handle();
    let h2 = handle.clone();

    let s = TcpListener::bind(&addr, &handle.clone());

    // Create a TCP listener which will listen for incoming connections
    let listener = lp.run(futures::done(s)).unwrap();

    info!("Listening on: {}", addr);

    let proxy = listener.incoming().for_each(|(sock, addr)| {
        debug!("Incoming connection on {}", addr);

        // TODO turn this into a pool managed by raft
        let pipe = TcpStream::connect(&backend, &h2).and_then(move |server| {

            Box::new(Pipe {
                client_addr: addr,
                server_addr: backend,
                client: sock,
                server: server,
                state: ConnectionState::ClientReading,
                send_buf: Vec::new(),
                recv_buf: Vec::new(),
            })

        }).and_then(|_| {
            debug!("Finished proxying");
            futures::finished(())
        }).map_err(|e| {
            error!("Error trying proxy - {}", e);
            ()
        });

        // spawn expects Item=Async(()), Error=()
        handle.spawn(pipe);

        Ok(())
    });

    lp.run(proxy).unwrap();
}
<|endoftext|>