<commit_before>use wlroots_sys::wlr_seat_pointer_request_set_cursor_event;

use {SeatClient, SurfaceHandle};

#[derive(Debug)]
pub struct SetCursorEvent {
    event: *mut wlr_seat_pointer_request_set_cursor_event
}

impl SetCursorEvent {
    pub(crate) unsafe fn from_ptr(event: *mut wlr_seat_pointer_request_set_cursor_event) -> Self {
        SetCursorEvent { event }
    }
    /// Get the seat client associated with the seat where this
    /// event is occurring.
    pub fn seat_client<'seat>(&'seat self) -> SeatClient<'seat> {
        unsafe { SeatClient::from_ptr((*self.event).seat_client) }
    }

    /// Get the surface that is providing the cursor to the seat.
    pub fn surface(&self) -> Option<SurfaceHandle> {
        unsafe {
            let surface = (*self.event).surface;
            if surface.is_null() {
                None
            } else {
                SurfaceHandle::from_ptr(surface)
            }
        }
    }

    pub fn serial(&self) -> u32 {
        unsafe { (*self.event).serial }
    }

    pub fn location(&self) -> (i32, i32) {
        unsafe { ((*self.event).hotspot_x, (*self.event).hotspot_y) }
    }
}
<commit_msg>fix return value of set_cursor event surface<commit_after>use wlroots_sys::wlr_seat_pointer_request_set_cursor_event;

use {SeatClient, SurfaceHandle};

#[derive(Debug)]
pub struct SetCursorEvent {
    event: *mut wlr_seat_pointer_request_set_cursor_event
}

impl SetCursorEvent {
    pub(crate) unsafe fn from_ptr(event: *mut wlr_seat_pointer_request_set_cursor_event) -> Self {
        SetCursorEvent { event }
    }
    /// Get the seat client associated with the seat where this
    /// event is occurring.
    pub fn seat_client<'seat>(&'seat self) -> SeatClient<'seat> {
        unsafe { SeatClient::from_ptr((*self.event).seat_client) }
    }

    /// Get the surface that is providing the cursor to the seat.
    pub fn surface(&self) -> Option<SurfaceHandle> {
        unsafe {
            let surface = (*self.event).surface;
            if surface.is_null() {
                None
            } else {
                Some(SurfaceHandle::from_ptr(surface))
            }
        }
    }

    pub fn serial(&self) -> u32 {
        unsafe { (*self.event).serial }
    }

    pub fn location(&self) -> (i32, i32) {
        unsafe { ((*self.event).hotspot_x, (*self.event).hotspot_y) }
    }
}
<|endoftext|>


<commit_before>#![crate_name="magog"]
#![feature(globs)]
#![feature(macro_rules)]
#![feature(tuple_indexing)]
#![comment = "Magog toplevel and display interface"]

extern crate image;
extern crate calx;
extern crate world;
extern crate time;

use calx::event;
use titlestate::TitleState;

pub mod drawable;
pub mod tilecache;
pub mod viewutil;
pub mod worldview;
mod gamestate;
mod titlestate;

pub trait State {
    fn process(&mut self, event: event::Event) -> Option<Transition>;
}

pub enum Transition {
    NewState(Box<State + Send>),
    Quit,
}

pub fn main() {
    let mut canvas = calx::Canvas::new();
    tilecache::init(&mut canvas);
    let mut state: Box<State + Send> = box TitleState::new();

    for evt in canvas.run() {
        match state.process(evt) {
            Some(Quit) => { return; }
            Some(NewState(s)) => { state = s; }
            _ => ()
        }
    }
}
<commit_msg>Fixed framerate<commit_after>#![crate_name="magog"]
#![feature(globs)]
#![feature(macro_rules)]
#![feature(tuple_indexing)]
#![comment = "Magog toplevel and display interface"]

extern crate image;
extern crate calx;
extern crate world;
extern crate time;

use calx::event;
use titlestate::TitleState;

pub mod drawable;
pub mod tilecache;
pub mod viewutil;
pub mod worldview;
mod gamestate;
mod titlestate;

pub trait State {
    fn process(&mut self, event: event::Event) -> Option<Transition>;
}

pub enum Transition {
    NewState(Box<State + Send>),
    Quit,
}

pub fn main() {
    let mut canvas = calx::Canvas::new()
        .set_frame_interval(0.030f64);
    tilecache::init(&mut canvas);
    let mut state: Box<State + Send> = box TitleState::new();

    for evt in canvas.run() {
        match state.process(evt) {
            Some(Quit) => { return; }
            Some(NewState(s)) => { state = s; }
            _ => ()
        }
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate time;

use hyper::Client;
use hyper::header::Connection;
use time::*;
use std::thread;
use std::sync::Arc;

struct Request {
    elapsed_time: f64
}

impl Request{
    fn new(elapsed_time: f64) -> Request{
        Request {
            elapsed_time: elapsed_time,
        }
    }

    fn mean_time(requests: Vec<Request>) {
        let mut total_request_times = 0;

        for r in requests {
            // https://github.com/rust-lang/rust/issues/24138
            // let elapsed_time = (r.elapsed_time * 100.0).round() / 100.0;
            //total_request_times = total_request_times + elapsed_time;
        }

        //total_request_times / requests.len()
    }
}

fn main() {
    let mut requests = Vec::new();
    let arc_requests = Arc::new(requests);

    for _x in 0..100 {
        let handle = thread::spawn(move || {
            let client = Client::new();
            let child_requests = arc_requests.clone();
            let start = time::precise_time_s();

            let res = client.get("http://jacob.uk.com")
                .header(Connection::close())
                .send().unwrap();

            let end = time::precise_time_s();

            child_numbers.push(Request::new(end-start));
        });

        handle.join().unwrap()
    }

    Request::mean_time(requests);
}
<commit_msg>Adds basic threading<commit_after>extern crate hyper;
extern crate time;

use hyper::Client;
use hyper::header::Connection;
use time::*;
use std::thread;
use std::sync::{Arc, Mutex};

struct Request {
    elapsed_time: f64
}

impl Request{
    fn new(elapsed_time: f64) -> Request{
        Request {
            elapsed_time: elapsed_time,
        }
    }
}

fn main() {
    let requests = Arc::new(Mutex::new(Vec::new()));

    for _x in 0..100 {
        let mut client = Client::new();
        let thread_items = requests.clone();

        let handle = thread::spawn(move || {
            let start = time::precise_time_s();

            let _res = client.get("http://jacob.uk.com")
                .header(Connection::close())
                .send().unwrap();

            let end = time::precise_time_s();

            thread_items.lock().unwrap().push((Request::new(end-start)));
        });

        handle.join().unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate chrono;
extern crate sxd_document;

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use rustc_serialize::json::Json;
use chrono::*;
use sxd_document::Package;
use sxd_document::writer::format_document;

fn help() {
    println!("usage: rust-msband-to-gpx infile.json [outfile.gpx]");
}

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        help();
        return;
    }

    // Process the arguments
    let input = args[1].to_owned();
    let output;
    if args.len() > 2 {
        let path = Path::new(&args[2]);
        output = path.file_stem().unwrap().to_str().unwrap();
    }
    else {
        let path = Path::new(&input);
        output = path.file_stem().unwrap().to_str().unwrap();
    }

    // Read the JSON file
    let mut file = File::open(&input).unwrap();
    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();

    let json = Json::from_str(&contents).unwrap();
    let object = json.as_object().unwrap();

    // Try to find the "Runs" array in the JSON
    if let Some(run_array) = object.get("Runs").and_then(|x| x.as_array()) {

        let mut run_number = 1;

        // Loop over each run
        for run in run_array.iter().map(|x| x.as_object().unwrap()) {

            println!("Run #{}", run_number);

            // Collect the distance and time array from the PaceData
            // This array will later help us calculate the time each WayPoint occurs
            let mut distance_and_time_array = Vec::<(f64, i64)>::new();
            if let Some(pace_data_array) = run.get("PaceData").and_then(|x| x.as_array()) {
                for pace_data in pace_data_array.iter().map(|x| x.as_object().unwrap()) {
                    match (pace_data.get("ScaledDistance").and_then(|x| x.as_f64()),
                        pace_data.get("ElapsedSeconds").and_then(|x| x.as_i64())) {

                        (Some(distance), Some(time)) => distance_and_time_array.push((distance, time)),
                        _ => {}
                    }
                }
            }

            if distance_and_time_array.len() == 0 {
                run_number += 1;
                continue;
            }
            let mut last_distance_and_time = distance_and_time_array.remove(0);

            // Process the start date from the MS timestamp
            let start_date_seconds = run.get("StartDate")
                .and_then(|x| x.as_string().unwrap_or("").split(&['(', ')'][..]).nth(1))
                .unwrap()
                .parse::<i64>()
                .ok()
                .unwrap() / 1_000;
            let naive_start_date = NaiveDateTime::from_timestamp(start_date_seconds, 0);
            let start_date = DateTime::<UTC>::from_utc(naive_start_date, UTC);

            // Construct GPX document
            let gpx_package = Package::new();
            let gpx_document = gpx_package.as_document();
            let gpx_element = gpx_document.create_element("gpx");
            gpx_element.set_attribute_value("creator", "convert-to-gpx");
            gpx_element.set_attribute_value("version", "1.1");
            gpx_element.set_attribute_value("xmlns", "http://www.topografix.com/GPX/1/1");
            gpx_element.set_attribute_value("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
            gpx_element.set_attribute_value("xsi:schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd");
            gpx_element.set_attribute_value("xmlns:gpxtpx", "http://www.garmin.com/xmlschemas/TrackPointExtension/v1");
            gpx_element.set_attribute_value("xmlns:gpxx", "http://www.garmin.com/xmlschemas/GpxExtensions/v3");
            gpx_document.root().append_child(gpx_element);

            let metadata_element = gpx_document.create_element("metadata");
            let time_element = gpx_document.create_element("time");
            time_element.append_child(gpx_document.create_text(&start_date.format("%Y-%m-%dT%H:%M:%SZ").to_string()));
            metadata_element.append_child(time_element);
            gpx_element.append_child(metadata_element);

            let track_element = gpx_document.create_element("trk");
            let track_segment_element = gpx_document.create_element("trkseg");
            track_element.append_child(track_segment_element);
            gpx_element.append_child(track_element);

            if let Some(map_point_array) = run.get("MapPoints").and_then(|x| x.as_array()) {
                for map_point in map_point_array.iter().map(|x| x.as_object().unwrap()) {
                    if let Some(location) = map_point.get("Location").and_then(|x| x.as_object()) {
                        match (location.get("Latitude").and_then(|x| x.as_f64()),
                            location.get("Longitude").and_then(|x| x.as_f64()),
                            map_point.get("TotalDistance").and_then(|x| x.as_f64()),
                            map_point.get("HeartRate").and_then(|x| x.as_i64())) {

                            (Some(latitude), Some(longitude), Some(distance), Some(heart_rate)) => {
                                while distance_and_time_array.len() > 0 && distance > distance_and_time_array[0].0 {
                                    last_distance_and_time = distance_and_time_array.remove(0);
                                }

                                // Try to extrapolate the elapsed seconds from the distance and time from the PaceData
                                let time;
                                if distance_and_time_array.len() > 0 {
                                    let scale = (distance - last_distance_and_time.0) / (distance_and_time_array[0].0 - last_distance_and_time.0);
                                    time = scale * (distance_and_time_array[0].1 - last_distance_and_time.1) as f64 + last_distance_and_time.1 as f64;
                                }
                                else {
                                    time = last_distance_and_time.1 as f64;
                                }

                                // Create the GPX elements for the track point
                                let trackpoint_element = gpx_document.create_element("trkpt");
                                trackpoint_element.set_attribute_value("lat", &format!("{}", latitude / 10_000_000.0));
                                trackpoint_element.set_attribute_value("lon", &format!("{}", longitude / 10_000_000.0));
                                track_segment_element.append_child(trackpoint_element);

                                let waypoint_date = start_date + Duration::seconds(time as i64);
                                let time_element = gpx_document.create_element("time");
                                time_element.append_child(gpx_document.create_text(&waypoint_date.format("%Y-%m-%dT%H:%M:%SZ").to_string()));
                                trackpoint_element.append_child(time_element);

                                let extensions_element = gpx_document.create_element("extensions");
                                let trackpoint_extension_element = gpx_document.create_element("gpxtpx:TrackPointExtension");
                                let heartrate_element = gpx_document.create_element("gpxtpx:hr");
                                heartrate_element.append_child(gpx_document.create_text(&format!("{}", heart_rate)));
                                trackpoint_extension_element.append_child(heartrate_element);
                                extensions_element.append_child(trackpoint_extension_element);
                                trackpoint_element.append_child(extensions_element);
                            },
                            _ => {}
                        }
                    }
                }

                // Output the XML file
                let output_filename = String::from(output) + &format!("-{}.gpx", run_number);
                let mut buffer = File::create(output_filename).ok().expect("There was a problem opening the GPX file.");
                format_document(&gpx_document, &mut buffer).ok().expect("There was a problem outputting the XML.");
            }
            else {
                println!("Could not find any MapPoints! Skipping this run...");
            }

            run_number += 1;
        }
    }
}
<commit_msg>Update heart_rate to be optional<commit_after>extern crate rustc_serialize;
extern crate chrono;
extern crate sxd_document;

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use rustc_serialize::json::Json;
use chrono::*;
use sxd_document::Package;
use sxd_document::writer::format_document;

fn help() {
    println!("usage: rust-msband-to-gpx infile.json [outfile.gpx]");
}

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        help();
        return;
    }

    // Process the arguments
    let input = args[1].to_owned();
    let output;
    if args.len() > 2 {
        let path = Path::new(&args[2]);
        output = path.file_stem().unwrap().to_str().unwrap();
    }
    else {
        let path = Path::new(&input);
        output = path.file_stem().unwrap().to_str().unwrap();
    }

    // Read the JSON file
    let mut file = File::open(&input).unwrap();
    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();

    let json = Json::from_str(&contents).unwrap();
    let object = json.as_object().unwrap();

    // Try to find the "Runs" array in the JSON
    if let Some(run_array) = object.get("Runs").and_then(|x| x.as_array()) {

        let mut run_number = 1;

        // Loop over each run
        for run in run_array.iter().map(|x| x.as_object().unwrap()) {

            println!("Run #{}", run_number);

            // Collect the distance and time array from the PaceData
            // This array will later help us calculate the time each WayPoint occurs
            let mut distance_and_time_array = Vec::<(f64, i64)>::new();
            if let Some(pace_data_array) = run.get("PaceData").and_then(|x| x.as_array()) {
                for pace_data in pace_data_array.iter().map(|x| x.as_object().unwrap()) {
                    match (pace_data.get("ScaledDistance").and_then(|x| x.as_f64()),
                        pace_data.get("ElapsedSeconds").and_then(|x| x.as_i64())) {

                        (Some(distance), Some(time)) => distance_and_time_array.push((distance, time)),
                        _ => {}
                    }
                }
            }

            if distance_and_time_array.len() == 0 {
                run_number += 1;
                continue;
            }
            let mut last_distance_and_time = distance_and_time_array.remove(0);

            // Process the start date from the MS timestamp
            let start_date_seconds = run.get("StartDate")
                .and_then(|x| x.as_string().unwrap_or("").split(&['(', ')'][..]).nth(1))
                .unwrap()
                .parse::<i64>()
                .ok()
                .unwrap() / 1_000;
            let naive_start_date = NaiveDateTime::from_timestamp(start_date_seconds, 0);
            let start_date = DateTime::<UTC>::from_utc(naive_start_date, UTC);

            // Construct GPX document
            let gpx_package = Package::new();
            let gpx_document = gpx_package.as_document();
            let gpx_element = gpx_document.create_element("gpx");
            gpx_element.set_attribute_value("creator", "convert-to-gpx");
            gpx_element.set_attribute_value("version", "1.1");
            gpx_element.set_attribute_value("xmlns", "http://www.topografix.com/GPX/1/1");
            gpx_element.set_attribute_value("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
            gpx_element.set_attribute_value("xsi:schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd");
            gpx_element.set_attribute_value("xmlns:gpxtpx", "http://www.garmin.com/xmlschemas/TrackPointExtension/v1");
            gpx_element.set_attribute_value("xmlns:gpxx", "http://www.garmin.com/xmlschemas/GpxExtensions/v3");
            gpx_document.root().append_child(gpx_element);

            let metadata_element = gpx_document.create_element("metadata");
            let time_element = gpx_document.create_element("time");
            time_element.append_child(gpx_document.create_text(&start_date.format("%Y-%m-%dT%H:%M:%SZ").to_string()));
            metadata_element.append_child(time_element);
            gpx_element.append_child(metadata_element);

            let track_element = gpx_document.create_element("trk");
            let track_segment_element = gpx_document.create_element("trkseg");
            track_element.append_child(track_segment_element);
            gpx_element.append_child(track_element);

            if let Some(map_point_array) = run.get("MapPoints").and_then(|x| x.as_array()) {
                for map_point in map_point_array.iter().map(|x| x.as_object().unwrap()) {
                    if let Some(location) = map_point.get("Location").and_then(|x| x.as_object()) {
                        match (location.get("Latitude").and_then(|x| x.as_f64()),
                            location.get("Longitude").and_then(|x| x.as_f64()),
                            map_point.get("TotalDistance").and_then(|x| x.as_f64()),
                            map_point.get("HeartRate").and_then(|x| x.as_i64())) {

                            (Some(latitude), Some(longitude), Some(distance), heart_rate) => {
                                while distance_and_time_array.len() > 0 && distance > distance_and_time_array[0].0 {
                                    last_distance_and_time = distance_and_time_array.remove(0);
                                }

                                // Try to extrapolate the elapsed seconds from the distance and time from the PaceData
                                let time;
                                if distance_and_time_array.len() > 0 {
                                    let scale = (distance - last_distance_and_time.0) / (distance_and_time_array[0].0 - last_distance_and_time.0);
                                    time = scale * (distance_and_time_array[0].1 - last_distance_and_time.1) as f64 + last_distance_and_time.1 as f64;
                                }
                                else {
                                    time = last_distance_and_time.1 as f64;
                                }

                                // Create the GPX elements for the track point
                                let trackpoint_element = gpx_document.create_element("trkpt");
                                trackpoint_element.set_attribute_value("lat", &format!("{}", latitude / 10_000_000.0));
                                trackpoint_element.set_attribute_value("lon", &format!("{}", longitude / 10_000_000.0));
                                track_segment_element.append_child(trackpoint_element);

                                let waypoint_date = start_date + Duration::seconds(time as i64);
                                let time_element = gpx_document.create_element("time");
                                time_element.append_child(gpx_document.create_text(&waypoint_date.format("%Y-%m-%dT%H:%M:%SZ").to_string()));
                                trackpoint_element.append_child(time_element);

                                if let Some(heart_rate) = heart_rate {
                                    let extensions_element = gpx_document.create_element("extensions");
                                    let trackpoint_extension_element = gpx_document.create_element("gpxtpx:TrackPointExtension");
                                    let heartrate_element = gpx_document.create_element("gpxtpx:hr");
                                    heartrate_element.append_child(gpx_document.create_text(&format!("{}", heart_rate)));
                                    trackpoint_extension_element.append_child(heartrate_element);
                                    extensions_element.append_child(trackpoint_extension_element);
                                    trackpoint_element.append_child(extensions_element);
                                }
                            },
                            _ => {}
                        }
                    }
                }

                // Output the XML file
                let output_filename = String::from(output) + &format!("-{}.gpx", run_number);
                let mut buffer = File::create(output_filename).ok().expect("There was a problem opening the GPX file.");
                format_document(&gpx_document, &mut buffer).ok().expect("There was a problem outputting the XML.");
            }
            else {
                println!("Could not find any MapPoints! Skipping this run...");
            }

            run_number += 1;
        }
    }
}
<|endoftext|>


<commit_before>//! `RustyBoy`

extern crate clap;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate sdl2;
extern crate ncurses;

pub mod assembler;
pub mod cpu;
pub mod debugger;
pub mod disasm;
pub mod io;

use cpu::*;
use debugger::graphics::*;
use io::sound::*;
use io::constants::*;
use io::input::*;
use io::graphics::*;
use io::memvis;
use io::vidram;

use std::num::Wrapping;
use clap::{Arg, App};
use sdl2::*;
use sdl2::rect::Rect;
use sdl2::rect::Point;

use log::LogLevelFilter;
use log4rs::append::console::ConsoleAppender;
use log4rs::encode::pattern::PatternEncoder;
use log4rs::config::{Appender, Config, Root};

use sdl2::keyboard::Keycode;

pub const NICER_COLOR: sdl2::pixels::Color = sdl2::pixels::Color::RGBA(139, 41, 2, 255);

#[allow(unused_variables)]
fn main() {
    // Set up logging
    let stdout = ConsoleAppender::builder()
        .encoder(Box::new(PatternEncoder::new("{h({l})} {m} {n}")))
        .build();

    // Command line arguments
    let matches = App::new("rusty-boy")
        .version("-0.1")
        .author("Mark McCaskey and friends")
        .about("Kappa")
        .arg(Arg::with_name("game")
            .short("g")
            .long("game")
            .value_name("FILE")
            .help("Specifies ROM to load")
            .required(true)
            .index(1)
            .takes_value(true))
        .arg(Arg::with_name("debug")
            .short("d")
            .multiple(true)
            .long("debug")
            .help("Runs in step-by-step debug mode")
            .takes_value(false))
        .arg(Arg::with_name("trace")
            .short("t")
            .multiple(true)
            .long("trace")
            .help("Runs with verbose trace")
            .takes_value(false))
        .get_matches();

    let config = Config::builder()
        .appender(Appender::builder().build("stdout", Box::new(stdout)))
        .build(Root::builder().appender("stdout").build(if matches.is_present("trace") {
            LogLevelFilter::Trace
        } else {
            LogLevelFilter::Debug
        }))
        .unwrap();

    // Attempt to read ROM first

    let rom_file = matches.value_of("game").expect("Could not open specified rom");
    let debug_mode = matches.is_present("debug");

    // Set up gameboy
    let mut gameboy = Cpu::new();

    // Set up debugging or command-line logging
    let mut debugger = if debug_mode {
        info!("Running in debug mode");
        Some(Debugger::new(&mut gameboy))
    } else {
        let handle = log4rs::init_config(config).unwrap();
        None
    };

    let mem_val_display_enabled = true;

    // Set up SDL; input
    let sdl_context = sdl2::init().unwrap();

    let mut device = setup_audio(&sdl_context);
    setup_controller_subsystem(&sdl_context);

    trace!("loading ROM");
    gameboy.load_rom(rom_file);

    // Set up graphics and window
    trace!("Opening window");
    let video_subsystem = sdl_context.video().unwrap();
    let window = video_subsystem.window(gameboy.get_game_name().as_str(),
                SCREEN_WIDTH,
                SCREEN_HEIGHT)
        .position_centered()
        .build()
        .unwrap();

    let mut renderer = window.renderer()
        .accelerated()
        .build()
        .unwrap();

    let mut scale = SCALE;

    // Set up time

    // let timer = sdl_context.timer().unwrap();
    let mut prev_time = 0;

    let mut cycle_count = 0;
    let mut clock_cycles = 0;
    let mut prev_hsync_cycles: u64 = 0;

    // Number of frames saved as screenshots
    let mut frame_num = Wrapping(0);

    let mut tile_data_mode_button = Toggle::new(Rect::new(MEM_DISP_WIDTH, MEM_DISP_HEIGHT, 24, 12),
                                                vec![TileDataSelect::Auto,
                                                     TileDataSelect::Mode1,
                                                     TileDataSelect::Mode2]);

    // This does not work as intended because of borrowing
    // let mut buttons = Vec::new();
    // buttons.push(tile_data_mode_button);

    'main: loop {
        for event in sdl_context.event_pump().unwrap().poll_iter() {
            use sdl2::event::Event;

            match event {
                Event::ControllerAxisMotion { axis, value: val, .. } => {
                    let dead_zone = 10000;
                    if val > dead_zone || val < -dead_zone {
                        debug!("Axis {:?} moved to {}", axis, val);
                        //                   match axis {
                        // controller::Axis::LeftX =>,
                        // controller::Axis::LeftY =>,
                        // _ => (),
                        // }
                        //
                    }
                }
                Event::ControllerButtonDown { button, .. } => {
                    debug!("Button {:?} down", button);
                    match button {
                        controller::Button::A => {
                            gameboy.press_a();
                            device.resume();
                        }
                        controller::Button::B => gameboy.press_b(),
                        controller::Button::Back => gameboy.press_select(),
                        controller::Button::Start => gameboy.press_start(),
                        _ => (),
                    }
                }

                Event::ControllerButtonUp { button, .. } => {
                    debug!("Button {:?} up", button);
                    match button {
                        controller::Button::A => {
                            gameboy.unpress_a();
                            device.pause();
                        }
                        controller::Button::B => gameboy.unpress_b(),
                        controller::Button::Back => gameboy.unpress_select(),
                        controller::Button::Start => gameboy.unpress_start(),
                        _ => (),
                    }
                }
                Event::Quit { .. } => {
                    info!("Program exiting!");
                    break 'main;
                }
                Event::KeyDown { keycode: Some(keycode), .. } => {
                    match keycode {
                        Keycode::Escape => {
                            info!("Program exiting!");
                            break 'main;
                        }
                        Keycode::F3 => gameboy.toggle_logger(),
                        Keycode::R => {
                            gameboy = Cpu::new();
                            gameboy.load_rom(rom_file);
                            // gameboy.event_log_enabled = event_log_enabled;
                        }
                        _ => (),
                    }
                }
                Event::MouseButtonDown { x, y, mouse_btn, .. } => {
                    match mouse_btn {
                        sdl2::mouse::MouseButton::Left => {
                            let scaled_x = x / scale as i32;
                            let scaled_y = y / scale as i32;
                            memvis::memvis_handle_click(&gameboy, scaled_x, scaled_y);
                            let point = Point::new(scaled_x, scaled_y);

                            if tile_data_mode_button.rect.contains(point) {
                                tile_data_mode_button.click();
                            }
                        }
                        sdl2::mouse::MouseButton::Right => {
                            // Jump to clicked addr and bring cpu back to life
                            let scaled_x = x / scale as i32;
                            let scaled_y = y / scale as i32;

                            if let Some(pc) = memvis::screen_coord_to_mem_addr(scaled_x, scaled_y) {
                                gameboy.pc = pc;
                                gameboy.state = cpu::constants::CpuState::Normal;
                            }

                        }
                        _ => (),
                    }
                }
                Event::MouseWheel { y, .. } => {
                    scale += y as f32;
                }
                _ => (),
            }
        }

        let current_op_time = if gameboy.state != cpu::constants::CpuState::Crashed {
            gameboy.dispatch_opcode() as u64
        } else {
            10 // FIXME think about what to return here or refactor code around this
        };

        cycle_count += current_op_time;
        clock_cycles += current_op_time;
        let timer_khz = gameboy.timer_frequency();
        let time_in_ms_per_cycle = (1000.0 / ((timer_khz as f64) * 1000.0)) as u64;
        clock_cycles += cycle_count;

        let ticks = cycle_count - prev_time;

        let time_in_cpu_cycle_per_cycle =
            ((time_in_ms_per_cycle as f64) / (1.0 / (4.19 * 1000.0 * 1000.0))) as u64;

        if clock_cycles >= time_in_cpu_cycle_per_cycle {
            //           std::thread::sleep_ms(16);
            // trace!("Incrementing the timer!");
            gameboy.timer_cycle();
            clock_cycles = 0;
        }

        let fake_display_hsync = true;
        if fake_display_hsync {
            // update LY respective to cycles spent execing instruction
            loop {
                if cycle_count < prev_hsync_cycles {
                    break;
                }
                gameboy.inc_ly();
                prev_hsync_cycles += CYCLES_PER_HSYNC;
            }
        }

        // Gameboy screen is 256x256
        // only 160x144 are displayed at a time
        //
        // Background tile map is 32x32 of tiles. Scrollx and scrolly
        // determine how this is actually rendered (it wraps)
        // These numbers index the tile data table
        //

        // 16384hz, call inc_div
        // CPU is at 4.194304MHz (or 1.05MHz) 105000000hz
        // hsync at 9198KHz = 9198000hz
        // vsync at 59.73Hz

        let color1 = sdl2::pixels::Color::RGBA(0, 0, 0, 255);
        let color2 = sdl2::pixels::Color::RGBA(255, 0, 0, 255);
        let color3 = sdl2::pixels::Color::RGBA(0, 0, 255, 255);
        let color4 = sdl2::pixels::Color::RGBA(255, 255, 255, 255);
        let color_lookup = [color1, color2, color3, color4];

        match renderer.set_scale(scale, scale) {
            Ok(_) => (),
            Err(_) => error!("Could not set render scale"),
        }

        // 1ms before drawing in terms of CPU time we must throw a vblank interrupt
        // TODO make this variable based on whether it's GB, SGB, etc.

        if ticks >= CPU_CYCLES_PER_VBLANK {
            if let Some(ref mut dbg) = debugger {
                dbg.step(&mut gameboy);
            }

            prev_time = cycle_count;
            renderer.set_draw_color(NICER_COLOR);
            renderer.clear();

            let tile_patterns_x_offset = (MEM_DISP_WIDTH + SCREEN_BUFFER_SIZE_X as i32) as i32 + 4;
            vidram::draw_tile_patterns(&mut renderer, &gameboy, tile_patterns_x_offset);

            // TODO add toggle for this also?
            let tile_map_offset = TILE_MAP_1_START;

            let bg_select = tile_data_mode_button.value().unwrap();

            let tile_patterns_offset = match bg_select {
                TileDataSelect::Auto =>
                    if gameboy.lcdc_bg_tile_map() {
                        TILE_PATTERN_TABLE_1_ORIGIN
                    } else {
                        TILE_PATTERN_TABLE_2_ORIGIN
                    },
                TileDataSelect::Mode1 => TILE_PATTERN_TABLE_1_ORIGIN,
                TileDataSelect::Mode2 => TILE_PATTERN_TABLE_2_ORIGIN,
            };

            let bg_disp_x_offset = MEM_DISP_WIDTH + 2;

            vidram::draw_background_buffer(&mut renderer,
                                           &gameboy,
                                           tile_map_offset,
                                           tile_patterns_offset,
                                           bg_disp_x_offset);

            if mem_val_display_enabled {
                // // dynamic mem access vis
                // memvis::draw_memory_values(&mut renderer, &gameboy);
                memvis::draw_memory_access(&mut renderer, &gameboy);

                memvis::draw_memory_events(&mut renderer, &mut gameboy);
            }

            tile_data_mode_button.draw(&mut renderer);

            //   00111100 1110001 00001000
            //   01111110 1110001 00010100
            //   11111111 1110001 00101010
            //

            // TODO add a way to enable/disable this while running
            let record_screen = false;
            if record_screen {
                save_screenshot(&renderer, format!("screen{:010}.bmp", frame_num.0));
                frame_num += Wrapping(1);
            }

            if gameboy.get_sound1() {
                device.resume();
            } else {
                device.pause();
            }

            let mut sound_system = device.lock();
            sound_system.wave_duty = gameboy.channel1_wave_pattern_duty();
            sound_system.phase_inc = 1.0 /
                                     (131072.0 / (2048 - gameboy.channel1_frequency()) as f32);
            sound_system.add = gameboy.channel1_sweep_increase();
            //            131072 / (2048 - gb)

            renderer.present();

            //            device.resume();
            // std::thread::sleep_ms(20);
            // device.pause();

            // Visualizations are slow and this is not the best way to do this anyway
            // std::thread::sleep(Duration::from_millis(FRAME_SLEEP));
        }

    }
}

// FIXME Results do not look like HSV, really :)
fn hue(h: u8) -> (f64, f64, f64) {
    let nh = (h as f64) / 256.0;
    let r = ((nh as f64) * 6.0 - 3.0).abs() - 1.0;
    let g = 2.0 - (((nh as f64) * 6.0) - 2.0).abs();
    let b = 2.0 - (((nh as f64) * 6.0) - 4.0).abs();

    (r, g, b)
}

#[allow(dead_code)]
fn hsv_to_rgb(h: u8) -> (u8, u8, u8) {
    let (r, g, b) = hue(h);

    let adj = |x| (x * 256.0) as u8;

    (adj(r), adj(g), adj(b))
}
<commit_msg>memvis: Print click-jump info<commit_after>//! `RustyBoy`

extern crate clap;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate sdl2;
extern crate ncurses;

pub mod assembler;
pub mod cpu;
pub mod debugger;
pub mod disasm;
pub mod io;

use cpu::*;
use debugger::graphics::*;
use io::sound::*;
use io::constants::*;
use io::input::*;
use io::graphics::*;
use io::memvis;
use io::vidram;

use std::num::Wrapping;
use clap::{Arg, App};
use sdl2::*;
use sdl2::rect::Rect;
use sdl2::rect::Point;

use log::LogLevelFilter;
use log4rs::append::console::ConsoleAppender;
use log4rs::encode::pattern::PatternEncoder;
use log4rs::config::{Appender, Config, Root};

use sdl2::keyboard::Keycode;

pub const NICER_COLOR: sdl2::pixels::Color = sdl2::pixels::Color::RGBA(139, 41, 2, 255);

#[allow(unused_variables)]
fn main() {
    // Set up logging
    let stdout = ConsoleAppender::builder()
        .encoder(Box::new(PatternEncoder::new("{h({l})} {m} {n}")))
        .build();

    // Command line arguments
    let matches = App::new("rusty-boy")
        .version("-0.1")
        .author("Mark McCaskey and friends")
        .about("Kappa")
        .arg(Arg::with_name("game")
            .short("g")
            .long("game")
            .value_name("FILE")
            .help("Specifies ROM to load")
            .required(true)
            .index(1)
            .takes_value(true))
        .arg(Arg::with_name("debug")
            .short("d")
            .multiple(true)
            .long("debug")
            .help("Runs in step-by-step debug mode")
            .takes_value(false))
        .arg(Arg::with_name("trace")
            .short("t")
            .multiple(true)
            .long("trace")
            .help("Runs with verbose trace")
            .takes_value(false))
        .get_matches();

    let config = Config::builder()
        .appender(Appender::builder().build("stdout", Box::new(stdout)))
        .build(Root::builder().appender("stdout").build(if matches.is_present("trace") {
            LogLevelFilter::Trace
        } else {
            LogLevelFilter::Debug
        }))
        .unwrap();

    // Attempt to read ROM first

    let rom_file = matches.value_of("game").expect("Could not open specified rom");
    let debug_mode = matches.is_present("debug");

    // Set up gameboy
    let mut gameboy = Cpu::new();

    // Set up debugging or command-line logging
    let mut debugger = if debug_mode {
        info!("Running in debug mode");
        Some(Debugger::new(&mut gameboy))
    } else {
        let handle = log4rs::init_config(config).unwrap();
        None
    };

    let mem_val_display_enabled = true;

    // Set up SDL; input
    let sdl_context = sdl2::init().unwrap();

    let mut device = setup_audio(&sdl_context);
    setup_controller_subsystem(&sdl_context);

    trace!("loading ROM");
    gameboy.load_rom(rom_file);

    // Set up graphics and window
    trace!("Opening window");
    let video_subsystem = sdl_context.video().unwrap();
    let window = video_subsystem.window(gameboy.get_game_name().as_str(),
                SCREEN_WIDTH,
                SCREEN_HEIGHT)
        .position_centered()
        .build()
        .unwrap();

    let mut renderer = window.renderer()
        .accelerated()
        .build()
        .unwrap();

    let mut scale = SCALE;

    // Set up time

    // let timer = sdl_context.timer().unwrap();
    let mut prev_time = 0;

    let mut cycle_count = 0;
    let mut clock_cycles = 0;
    let mut prev_hsync_cycles: u64 = 0;

    // Number of frames saved as screenshots
    let mut frame_num = Wrapping(0);

    let mut tile_data_mode_button = Toggle::new(Rect::new(MEM_DISP_WIDTH, MEM_DISP_HEIGHT, 24, 12),
                                                vec![TileDataSelect::Auto,
                                                     TileDataSelect::Mode1,
                                                     TileDataSelect::Mode2]);

    // This does not work as intended because of borrowing
    // let mut buttons = Vec::new();
    // buttons.push(tile_data_mode_button);

    'main: loop {
        for event in sdl_context.event_pump().unwrap().poll_iter() {
            use sdl2::event::Event;

            match event {
                Event::ControllerAxisMotion { axis, value: val, .. } => {
                    let dead_zone = 10000;
                    if val > dead_zone || val < -dead_zone {
                        debug!("Axis {:?} moved to {}", axis, val);
                        //                   match axis {
                        // controller::Axis::LeftX =>,
                        // controller::Axis::LeftY =>,
                        // _ => (),
                        // }
                        //
                    }
                }
                Event::ControllerButtonDown { button, .. } => {
                    debug!("Button {:?} down", button);
                    match button {
                        controller::Button::A => {
                            gameboy.press_a();
                            device.resume();
                        }
                        controller::Button::B => gameboy.press_b(),
                        controller::Button::Back => gameboy.press_select(),
                        controller::Button::Start => gameboy.press_start(),
                        _ => (),
                    }
                }

                Event::ControllerButtonUp { button, .. } => {
                    debug!("Button {:?} up", button);
                    match button {
                        controller::Button::A => {
                            gameboy.unpress_a();
                            device.pause();
                        }
                        controller::Button::B => gameboy.unpress_b(),
                        controller::Button::Back => gameboy.unpress_select(),
                        controller::Button::Start => gameboy.unpress_start(),
                        _ => (),
                    }
                }
                Event::Quit { .. } => {
                    info!("Program exiting!");
                    break 'main;
                }
                Event::KeyDown { keycode: Some(keycode), .. } => {
                    match keycode {
                        Keycode::Escape => {
                            info!("Program exiting!");
                            break 'main;
                        }
                        Keycode::F3 => gameboy.toggle_logger(),
                        Keycode::R => {
                            // Reset/reload emu
                            gameboy = Cpu::new();
                            gameboy.load_rom(rom_file);
                            // gameboy.event_log_enabled = event_log_enabled;
                        }
                        _ => (),
                    }
                }
                Event::MouseButtonDown { x, y, mouse_btn, .. } => {
                    match mouse_btn {
                        sdl2::mouse::MouseButton::Left => {
                            // Print info about clicked address
                            let scaled_x = x / scale as i32;
                            let scaled_y = y / scale as i32;
                            memvis::memvis_handle_click(&gameboy, scaled_x, scaled_y);

                            // Switch Tile Map manually
                            let point = Point::new(scaled_x, scaled_y);
                            if tile_data_mode_button.rect.contains(point) {
                                tile_data_mode_button.click();
                            }
                        }
                        sdl2::mouse::MouseButton::Right => {
                            // Jump to clicked addr and bring cpu back to life
                            let scaled_x = x / scale as i32;
                            let scaled_y = y / scale as i32;

                            if let Some(pc) = memvis::screen_coord_to_mem_addr(scaled_x, scaled_y) {
                                info!("Jumping to ${:04X}", pc);
                                gameboy.pc = pc;
                                if gameboy.state != cpu::constants::CpuState::Normal {
                                    info!("CPU was '{:?}', forcing run.", gameboy.state);
                                    gameboy.state = cpu::constants::CpuState::Normal;
                                }
                            }

                        }
                        _ => (),
                    }
                }
                Event::MouseWheel { y, .. } => {
                    scale += y as f32;
                }
                _ => (),
            }
        }

        let current_op_time = if gameboy.state != cpu::constants::CpuState::Crashed {
            gameboy.dispatch_opcode() as u64
        } else {
            10 // FIXME think about what to return here or refactor code around this
        };

        cycle_count += current_op_time;
        clock_cycles += current_op_time;
        let timer_khz = gameboy.timer_frequency();
        let time_in_ms_per_cycle = (1000.0 / ((timer_khz as f64) * 1000.0)) as u64;
        clock_cycles += cycle_count;

        let ticks = cycle_count - prev_time;

        let time_in_cpu_cycle_per_cycle =
            ((time_in_ms_per_cycle as f64) / (1.0 / (4.19 * 1000.0 * 1000.0))) as u64;

        if clock_cycles >= time_in_cpu_cycle_per_cycle {
            //           std::thread::sleep_ms(16);
            // trace!("Incrementing the timer!");
            gameboy.timer_cycle();
            clock_cycles = 0;
        }

        let fake_display_hsync = true;
        if fake_display_hsync {
            // update LY respective to cycles spent execing instruction
            loop {
                if cycle_count < prev_hsync_cycles {
                    break;
                }
                gameboy.inc_ly();
                prev_hsync_cycles += CYCLES_PER_HSYNC;
            }
        }

        // Gameboy screen is 256x256
        // only 160x144 are displayed at a time
        //
        // Background tile map is 32x32 of tiles. Scrollx and scrolly
        // determine how this is actually rendered (it wraps)
        // These numbers index the tile data table
        //

        // 16384hz, call inc_div
        // CPU is at 4.194304MHz (or 1.05MHz) 105000000hz
        // hsync at 9198KHz = 9198000hz
        // vsync at 59.73Hz

        let color1 = sdl2::pixels::Color::RGBA(0, 0, 0, 255);
        let color2 = sdl2::pixels::Color::RGBA(255, 0, 0, 255);
        let color3 = sdl2::pixels::Color::RGBA(0, 0, 255, 255);
        let color4 = sdl2::pixels::Color::RGBA(255, 255, 255, 255);
        let color_lookup = [color1, color2, color3, color4];

        match renderer.set_scale(scale, scale) {
            Ok(_) => (),
            Err(_) => error!("Could not set render scale"),
        }

        // 1ms before drawing in terms of CPU time we must throw a vblank interrupt
        // TODO make this variable based on whether it's GB, SGB, etc.

        if ticks >= CPU_CYCLES_PER_VBLANK {
            if let Some(ref mut dbg) = debugger {
                dbg.step(&mut gameboy);
            }

            prev_time = cycle_count;
            renderer.set_draw_color(NICER_COLOR);
            renderer.clear();

            let tile_patterns_x_offset = (MEM_DISP_WIDTH + SCREEN_BUFFER_SIZE_X as i32) as i32 + 4;
            vidram::draw_tile_patterns(&mut renderer, &gameboy, tile_patterns_x_offset);

            // TODO add toggle for this also?
            let tile_map_offset = TILE_MAP_1_START;

            let bg_select = tile_data_mode_button.value().unwrap();

            let tile_patterns_offset = match bg_select {
                TileDataSelect::Auto =>
                    if gameboy.lcdc_bg_tile_map() {
                        TILE_PATTERN_TABLE_1_ORIGIN
                    } else {
                        TILE_PATTERN_TABLE_2_ORIGIN
                    },
                TileDataSelect::Mode1 => TILE_PATTERN_TABLE_1_ORIGIN,
                TileDataSelect::Mode2 => TILE_PATTERN_TABLE_2_ORIGIN,
            };

            let bg_disp_x_offset = MEM_DISP_WIDTH + 2;

            vidram::draw_background_buffer(&mut renderer,
                                           &gameboy,
                                           tile_map_offset,
                                           tile_patterns_offset,
                                           bg_disp_x_offset);

            if mem_val_display_enabled {
                // // dynamic mem access vis
                // memvis::draw_memory_values(&mut renderer, &gameboy);
                memvis::draw_memory_access(&mut renderer, &gameboy);

                memvis::draw_memory_events(&mut renderer, &mut gameboy);
            }

            tile_data_mode_button.draw(&mut renderer);

            //   00111100 1110001 00001000
            //   01111110 1110001 00010100
            //   11111111 1110001 00101010
            //

            // TODO add a way to enable/disable this while running
            let record_screen = false;
            if record_screen {
                save_screenshot(&renderer, format!("screen{:010}.bmp", frame_num.0));
                frame_num += Wrapping(1);
            }

            if gameboy.get_sound1() {
                device.resume();
            } else {
                device.pause();
            }

            let mut sound_system = device.lock();
            sound_system.wave_duty = gameboy.channel1_wave_pattern_duty();
            sound_system.phase_inc = 1.0 /
                                     (131072.0 / (2048 - gameboy.channel1_frequency()) as f32);
            sound_system.add = gameboy.channel1_sweep_increase();
            //            131072 / (2048 - gb)

            renderer.present();

            //            device.resume();
            // std::thread::sleep_ms(20);
            // device.pause();

            // Visualizations are slow and this is not the best way to do this anyway
            // std::thread::sleep(Duration::from_millis(FRAME_SLEEP));
        }

    }
}

// FIXME Results do not look like HSV, really :)
fn hue(h: u8) -> (f64, f64, f64) {
    let nh = (h as f64) / 256.0;
    let r = ((nh as f64) * 6.0 - 3.0).abs() - 1.0;
    let g = 2.0 - (((nh as f64) * 6.0) - 2.0).abs();
    let b = 2.0 - (((nh as f64) * 6.0) - 4.0).abs();

    (r, g, b)
}

#[allow(dead_code)]
fn hsv_to_rgb(h: u8) -> (u8, u8, u8) {
    let (r, g, b) = hue(h);

    let adj = |x| (x * 256.0) as u8;

    (adj(r), adj(g), adj(b))
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

#[macro_use] extern crate quick_error;
extern crate regex;
extern crate toml;
extern crate semver;

use std::process::exit;

use semver::Identifier;

mod config;
mod error;
mod cmd;
mod git;
mod cargo;

fn execute() -> Result<i32, error::FatalError> {

    // STEP 0: Check if working directory is clean
    let git_clean = try!(git::status());
    if git_clean {
        println!("Working directory is clean");
    } else {
        println!("Uncommitted changes detected, please commit before release");
        return Ok(128);
    }

    // STEP 1: Read version from Cargo.toml and remove
    let result = try!(config::parse_cargo_config());

    let mut version = result.get("package")
        .and_then(|f| f.as_table())
        .and_then(|f| f.get("version"))
        .and_then(|f| f.as_str())
        .and_then(|f| config::parse_version(f).ok())
        .unwrap();

    // STEP 2: Remove pre extension, save and commit
    if version.is_prerelease() {
        version.pre.clear();
        let new_version_string = version.to_string();
        try!(config::rewrite_cargo_version(&new_version_string));

        let commit_msg = format!("(cargo-release) version {}", new_version_string);
        if !try!(git::commit_all(&commit_msg)) {
            // commit failed, abort release
            return Ok(128);
        }
    }

    // STEP 3: Tag
    let current_version = version.to_string();
    if !try!(git::tag(&current_version)) {
        // tag failed, abort release
        return Ok(128);
    }

    // STEP 4: cargo publish
    if !try!(cargo::publish()) {
        return Ok(128);
    }

    // STEP 5: bump version
    version.increment_patch();
    version.pre.push(Identifier::AlphaNumeric("pre".to_owned()));
    println!("Starting next development cycle {}", version);
    let updated_version_string = version.to_string();
    try!(config::rewrite_cargo_version(&updated_version_string));
    let commit_msg = format!("(cargo-release) start next development cycle {}",
                             updated_version_string);
    if !try!(git::commit_all(&commit_msg)) {
        return Ok(128);
    }

    // STEP 6: git push
    if !try!(git::push()) {
        return Ok(128);
    }
    Ok(0)
}

fn main() {
    match execute() {
        Ok(code) => exit(code),
        Err(e) => {
            println!("Fatal: {}", e);
            exit(128);
        }
    }
}
<commit_msg>(fix) move publish before tag<commit_after>#![allow(dead_code)]

#[macro_use] extern crate quick_error;
extern crate regex;
extern crate toml;
extern crate semver;

use std::process::exit;

use semver::Identifier;

mod config;
mod error;
mod cmd;
mod git;
mod cargo;

fn execute() -> Result<i32, error::FatalError> {

    // STEP 0: Check if working directory is clean
    let git_clean = try!(git::status());
    if git_clean {
        println!("Working directory is clean");
    } else {
        println!("Uncommitted changes detected, please commit before release");
        return Ok(128);
    }

    // STEP 1: Read version from Cargo.toml and remove
    let result = try!(config::parse_cargo_config());

    let mut version = result.get("package")
        .and_then(|f| f.as_table())
        .and_then(|f| f.get("version"))
        .and_then(|f| f.as_str())
        .and_then(|f| config::parse_version(f).ok())
        .unwrap();

    // STEP 2: Remove pre extension, save and commit
    if version.is_prerelease() {
        version.pre.clear();
        let new_version_string = version.to_string();
        try!(config::rewrite_cargo_version(&new_version_string));

        let commit_msg = format!("(cargo-release) version {}", new_version_string);
        if !try!(git::commit_all(&commit_msg)) {
            // commit failed, abort release
            return Ok(128);
        }
    }

    // STEP 3: cargo publish
    if !try!(cargo::publish()) {
        return Ok(128);
    }

    // STEP 4: Tag
    let current_version = version.to_string();
    if !try!(git::tag(&current_version)) {
        // tag failed, abort release
        return Ok(128);
    }

    // STEP 5: bump version
    version.increment_patch();
    version.pre.push(Identifier::AlphaNumeric("pre".to_owned()));
    println!("Starting next development cycle {}", version);
    let updated_version_string = version.to_string();
    try!(config::rewrite_cargo_version(&updated_version_string));
    let commit_msg = format!("(cargo-release) start next development cycle {}",
                             updated_version_string);
    if !try!(git::commit_all(&commit_msg)) {
        return Ok(128);
    }

    // STEP 6: git push
    if !try!(git::push()) {
        return Ok(128);
    }
    Ok(0)
}

fn main() {
    match execute() {
        Ok(code) => exit(code),
        Err(e) => {
            println!("Fatal: {}", e);
            exit(128);
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;
use std::net::{Ipv4Addr, SocketAddrV4, UdpSocket};
use std::io::{BufReader, Read, Error};
use std::fs::File;

#[ repr(u16) ]
enum PacketType{
    RRQ = 1,
    WRQ,
    DATA,
    ACK,
    ERROR
}

static NETASCII: &'static str = "netascii";
static OCTET: &'static str = "octet";

fn create_rrq_wrq_packet(p_type: PacketType, file_name: String, mode : &'static str)->Vec<u8>{
    let mut v = Vec::with_capacity(2+file_name.len()+1+mode.len()+1);
    v.push(0);
    v.push(p_type as u8);
    v.extend(file_name.as_bytes());
    v.push(0);//zero terminator
    v.extend(mode.as_bytes());
    v.push(0);//zero terminator
    v
}

struct FileStream<'a, Read>{
    file_name : String,
    start : u64,
    end:u64,
    buf:Option<&'a mut[u8]>,
    reader : BufReader<Read>
}

impl<'a> FileStream<'a, std::fs::File>{ //std::fs::File because we are talking concrete implementation
    fn new(file_name:String)->Option<Self>{
        let f = match std::fs::File::open(file_name.clone()){
            Ok(handle) => Some(handle),
            Err(msg) => None

        };
        if f.is_some(){
            let mut fs = FileStream{
                file_name:file_name,
                start: 0,
                end: 0,
                reader : BufReader::with_capacity(512, f.unwrap()),
                buf : None
            };
            //fs.reader.read(&mut buf);
            Some(fs)
        }
        else{
            None
        }
    }
}

impl<'a> Iterator for FileStream<'a, std::fs::File>{
    type Item = ([u8;512], usize);
    fn next(&mut self)->Option<Self::Item>{
        let mut arr = [0;512];
        let num_bytes_read = self.reader.read(&mut arr);
        let mut i = 0usize;
        for c in self.buf.as_mut().unwrap().iter_mut(){
            *c = arr[i];
        }
        Some((arr, num_bytes_read.unwrap()))
    }
}

/*
fn create_data_packet()->Vec<u8>{

}
*/

fn recv() -> Result<(), Error> {
    // Define the local connection information
    let ip = Ipv4Addr::new(127, 0, 0, 1);
    let connection = SocketAddrV4::new(ip, 69);

    // Bind the socket
    let socket = try!(UdpSocket::bind(connection));

    // Read from the socket
    let mut buf = [0; 10];
    let (amt, src) = try!(socket.recv_from(&mut buf));

    // Print only the valid data (slice)
    println!("recvr recvd: {:?}", &buf[0 .. amt]);
    println!("recv sending...");
    socket.send_to(&[5,4,3], src);

    Ok(())
}

fn send() -> Result<(), Error> {
    // Define the local connection (to send the data from)
    let ip = Ipv4Addr::new(127, 0, 0, 1);
    //TODO generate port # using rand
    let connection = SocketAddrV4::new(ip, 9992);

    // Bind the socket
    let socket = try!(UdpSocket::bind(connection));

    // Define the remote connection (to send the data to)
    let connection2 = SocketAddrV4::new(ip, 69);

    // Send data via the socket
    let buf = &[0x01, 0x02, 0x03];
    try!(socket.send_to(buf, connection2));
    println!("sender sent {:?}", buf);

    let mut buf  = [0; 10];
    socket.recv_from(&mut buf);

    println!("sender recvd {:?}", buf);
    Ok(())
}

fn main() {

    let args : Vec<_> = std::env::args().collect();
    println!("{}", args[1]);
    if args[1] == "0"{
        println!("passed 0");
        recv();
    }
    else{
        println!("passed 1");
        send();
    }
}
<commit_msg>Use array instead of a borrowed slice<commit_after>extern crate rand;
use std::net::{Ipv4Addr, SocketAddrV4, UdpSocket};
use std::io::{BufReader, Read, Error};
use std::fs::File;

#[ repr(u16) ]
enum PacketType{
    RRQ = 1,
    WRQ,
    DATA,
    ACK,
    ERROR
}

static NETASCII: &'static str = "netascii";
static OCTET: &'static str = "octet";

fn create_rrq_wrq_packet(p_type: PacketType, file_name: String, mode : &'static str)->Vec<u8>{
    let mut v = Vec::with_capacity(2+file_name.len()+1+mode.len()+1);
    v.push(0);
    v.push(p_type as u8);
    v.extend(file_name.as_bytes());
    v.push(0);//zero terminator
    v.extend(mode.as_bytes());
    v.push(0);//zero terminator
    v
}

struct FileStream<Read>{
    file_name : String,
    start : u64,
    end:u64,
    buf:[u8;512],
    reader : BufReader<Read>
}

impl FileStream<std::fs::File>{ //std::fs::File because we are talking concrete implementation
    fn new(file_name:String)->Option<Self>{
        let f = match std::fs::File::open(file_name.clone()){
            Ok(handle) => Some(handle),
            Err(msg) => None

        };
        if f.is_some(){
            let mut fs = FileStream{
                file_name:file_name,
                start: 0,
                end: 0,
                reader : BufReader::with_capacity(512, f.unwrap()),
                buf : [0;512]
            };
            Some(fs)
        }
        else{
            println!("cant open file");
            None
        }
    }
}

impl Iterator for FileStream<std::fs::File>{
    type Item = ([u8;512], usize);
    fn next(&mut self)->Option<Self::Item>{
        let mut arr = [0;512];
        let num_bytes_read = self.reader.read(&mut arr);
        println!("{:?}", num_bytes_read);
        let mut i = 0usize;
        for c in self.buf.iter_mut(){
            *c = arr[i];
        }
        Some((arr, num_bytes_read.unwrap()))
    }
}

/*
fn create_data_packet()->Vec<u8>{

}
*/

fn recv() -> Result<(), Error> {
    // Define the local connection information
    let ip = Ipv4Addr::new(127, 0, 0, 1);
    let connection = SocketAddrV4::new(ip, 6900);

    println!("rcvr waiting for incoming data");
    // Bind the socket
    let socket = try!(UdpSocket::bind(connection));
    println!("rcvr waiting for incoming data");

    // Read from the socket
    let mut buf = [0; 512];
    let (amt, src) = try!(socket.recv_from(&mut buf));

    // Print only the valid data (slice)
    println!("recvr recvd: {:?}", &buf[0 .. amt]);
    println!("recv sending...");
    socket.send_to(&[5,4,3], src);

    Ok(())
}

fn send() -> Result<(), Error> {
    // Define the local connection (to send the data from)
    let ip = Ipv4Addr::new(127, 0, 0, 1);
    //TODO generate port # using rand
    let connection = SocketAddrV4::new(ip, 9992);

    // Bind the socket
    let socket = try!(UdpSocket::bind(connection));

    // Define the remote connection (to send the data to)
    let connection2 = SocketAddrV4::new(ip, 6900);

    // Send data via the socket
    let mut fs = FileStream::new("/home/abhi/code/rust/fei/target/debug/foo.txt".to_string()).unwrap();
    let (buf, num_bytes_read) = fs.next().unwrap();
    try!(socket.send_to(&buf, connection2));

    let mut buf  = [0; 10];
    socket.recv_from(&mut buf);

    println!("sender recvd {:?}", buf);
    Ok(())
}

fn main() {

    let args : Vec<_> = std::env::args().collect();
    println!("{}", args[1]);
    if args[1] == "0"{
        println!("passed 0");
        match recv(){
            Ok(_) => {},
            Err(msg) => println!("{}", msg)

        }
    }
    else{
        println!("passed 1");
        send();
    }
}
<|endoftext|>


<commit_before>extern crate ramp;
extern crate bufstream;

use std::sync::mpsc::channel;
use std::thread;
use std::sync::{RwLock, Arc};
use std::net::{TcpListener, TcpStream};
use std::io::{Read, BufRead};

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

use bufstream::BufStream;

use ramp::Database;

type DB = Arc<RwLock<Database>>;

//
// impl RampServer {
//     fn new() -> RampServer {
//         // create a new Database, wrap in RwLock and Arc
//         let db = RwLock::new(Database::new());
//         RampServer{db:db}
//     }
// }
//
// impl ramp_interface::Server for RampServer {
//     fn prepare(&mut self, mut context: ramp_interface::PrepareContext) {
//         println!("Preparing");
//         {
//             let (params, mut results) = context.get();
//             let key = params.get_key().unwrap();
//             let value = params.get_value().unwrap();
//
//             let deps = {
//                 let target = params.get_dependencies().unwrap();
//                 let size = target.len();
//                 let mut entries = Vec::with_capacity(size as usize);
//                 for i in 0..size {
//                     entries.push(target.get(i).unwrap().to_string());
//                 }
//                 entries
//             };
//
//             // let deps = params.get_dependencies().unwrap();
//             let timestamp = params.get_timestamp();
//
//             println!("Acquiring write lock");
//             let mut db = self.db.write().unwrap(); // hold lock till prepare is done
//             db.prepare(key.to_string(), value.to_string(), deps, timestamp);
//         }
//
//         context.done();
//         println!("Prepared");
//     }
//
//     fn commit(&mut self, mut context: ramp_interface::CommitContext) {
//         println!("Committing");
//         {
//             let (params, mut results) = context.get();
//             let ts = params.get_timestamp();
//
//             println!("Acquiring write lock");
//             let mut db = self.db.write().unwrap();
//             println!("Write lock acquired");
//             db.commit(ts);
//
//         }
//
//         context.done();
//     }
//
//     fn get(&mut self, mut context: ramp_interface::GetContext) {
//         {
//             let (params, mut results) = context.get();
//             let key = params.get_key().unwrap();
//
//             let mut db = self.db.write().unwrap();
//             let version = db.get(key.to_string());
//
//             match version {
//                 Some(v) => {
//                     println!("Found version {} {}", v.timestamp, &v.value);
//                     let mut r = results.init_result();
//                     let mut ver = r.init_version();
//                     ver.set_value(&v.value);
//                     ver.set_timestamp(v.timestamp);
//
//                     let len = v.dependencies.len() as u32;
//                     let mut deps = ver.init_dependencies(len);
//
//                     println!("{} dependencies: {:?}", len, v.dependencies);
//                     for i in 0..len {
//                         println!("Setting dependency {}",i);
//                         deps.set(i as u32, &v.dependencies.get(i as usize).unwrap());
//                     }
//                     println!("Deps set for get return");
//                 },
//                 None => {
//                     let mut r = results.init_result();
//                     r.set_none(());
//                 }
//             };
//
//         }
//         context.done();
//     }
//
//     fn get_version(&mut self, mut context: ramp_interface::GetVersionContext) {
//         {
//             println!("Getting specific version");
//             let (params, mut results) = context.get();
//             let key = params.get_key().unwrap();
//             let timestamp = params.get_timestamp();
//
//             let mut db = self.db.write().unwrap();
//             let version = db.get_version(key.to_string(), timestamp);
//
//             match version {
//                 Some(v) => {
//                     let mut r = results.init_result();
//                     let mut ver = r.init_version();
//                     ver.set_value(&v.value);
//                     ver.set_timestamp(v.timestamp);
//
//                     let len = v.dependencies.len() as u32;
//                     let mut deps = ver.init_dependencies(len);
//                     for i in 0..len {
//                         deps.set(i as u32, &v.dependencies.get(i as usize).unwrap());
//                     }
//                 },
//                 None => {
//                     // let mut r = results.init_result();
//                     // r.set_none(());
//                 }
//             };
//         }
//
//         context.done();
//     }
// }

fn main() {
    /*
    Logger notes:
    RUST_LOG=error ./main
    RUST_LOG=info
    http://rust-lang.github.io/log/env_logger/
    */

    info!("Starting up RAMP socket server!");
    let db = Arc::new(RwLock::new(Database::new()));
    let listener = TcpListener::bind("127.0.0.1:6000").unwrap();

    info!("Socket bound");

    for stream in listener.incoming() {
        // info!("connection established, spawning new thread");
        let db2 = db.clone();
        match stream {
            Ok(stream) => {
                thread::spawn(move || {
                    handle_client(stream, db2)
                    });
            },
            Err(e) => {}
        }
    }

    info!("Goodbye forever.");
}

fn handle_client(mut stream: TcpStream, mut db: DB ) {
    info!("Starting new client thread");

    let mut buf = BufStream::new(stream);

    let mut buffer = String::new();
    loop {
        match  buf.read_line(&mut buffer) {
            Ok(bytes) => {
                println!("ok - command received {}", bytes);
            },
            Err(_) => {
                println!("Error, leaving");
                return ();
            }
        };
    }

}
<commit_msg>using iterator instead of match<commit_after>extern crate ramp;
extern crate bufstream;

use std::sync::mpsc::channel;
use std::thread;
use std::sync::{RwLock, Arc};
use std::net::{TcpListener, TcpStream};
use std::io::{Read, BufRead};

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

use bufstream::BufStream;

use ramp::Database;

type DB = Arc<RwLock<Database>>;

//
// impl RampServer {
//     fn new() -> RampServer {
//         // create a new Database, wrap in RwLock and Arc
//         let db = RwLock::new(Database::new());
//         RampServer{db:db}
//     }
// }
//
// impl ramp_interface::Server for RampServer {
//     fn prepare(&mut self, mut context: ramp_interface::PrepareContext) {
//         println!("Preparing");
//         {
//             let (params, mut results) = context.get();
//             let key = params.get_key().unwrap();
//             let value = params.get_value().unwrap();
//
//             let deps = {
//                 let target = params.get_dependencies().unwrap();
//                 let size = target.len();
//                 let mut entries = Vec::with_capacity(size as usize);
//                 for i in 0..size {
//                     entries.push(target.get(i).unwrap().to_string());
//                 }
//                 entries
//             };
//
//             // let deps = params.get_dependencies().unwrap();
//             let timestamp = params.get_timestamp();
//
//             println!("Acquiring write lock");
//             let mut db = self.db.write().unwrap(); // hold lock till prepare is done
//             db.prepare(key.to_string(), value.to_string(), deps, timestamp);
//         }
//
//         context.done();
//         println!("Prepared");
//     }
//
//     fn commit(&mut self, mut context: ramp_interface::CommitContext) {
//         println!("Committing");
//         {
//             let (params, mut results) = context.get();
//             let ts = params.get_timestamp();
//
//             println!("Acquiring write lock");
//             let mut db = self.db.write().unwrap();
//             println!("Write lock acquired");
//             db.commit(ts);
//
//         }
//
//         context.done();
//     }
//
//     fn get(&mut self, mut context: ramp_interface::GetContext) {
//         {
//             let (params, mut results) = context.get();
//             let key = params.get_key().unwrap();
//
//             let mut db = self.db.write().unwrap();
//             let version = db.get(key.to_string());
//
//             match version {
//                 Some(v) => {
//                     println!("Found version {} {}", v.timestamp, &v.value);
//                     let mut r = results.init_result();
//                     let mut ver = r.init_version();
//                     ver.set_value(&v.value);
//                     ver.set_timestamp(v.timestamp);
//
//                     let len = v.dependencies.len() as u32;
//                     let mut deps = ver.init_dependencies(len);
//
//                     println!("{} dependencies: {:?}", len, v.dependencies);
//                     for i in 0..len {
//                         println!("Setting dependency {}",i);
//                         deps.set(i as u32, &v.dependencies.get(i as usize).unwrap());
//                     }
//                     println!("Deps set for get return");
//                 },
//                 None => {
//                     let mut r = results.init_result();
//                     r.set_none(());
//                 }
//             };
//
//         }
//         context.done();
//     }
//
//     fn get_version(&mut self, mut context: ramp_interface::GetVersionContext) {
//         {
//             println!("Getting specific version");
//             let (params, mut results) = context.get();
//             let key = params.get_key().unwrap();
//             let timestamp = params.get_timestamp();
//
//             let mut db = self.db.write().unwrap();
//             let version = db.get_version(key.to_string(), timestamp);
//
//             match version {
//                 Some(v) => {
//                     let mut r = results.init_result();
//                     let mut ver = r.init_version();
//                     ver.set_value(&v.value);
//                     ver.set_timestamp(v.timestamp);
//
//                     let len = v.dependencies.len() as u32;
//                     let mut deps = ver.init_dependencies(len);
//                     for i in 0..len {
//                         deps.set(i as u32, &v.dependencies.get(i as usize).unwrap());
//                     }
//                 },
//                 None => {
//                     // let mut r = results.init_result();
//                     // r.set_none(());
//                 }
//             };
//         }
//
//         context.done();
//     }
// }

fn main() {
    /*
    Logger notes:
    RUST_LOG=error ./main
    RUST_LOG=info
    http://rust-lang.github.io/log/env_logger/
    */

    info!("Starting up RAMP socket server!");
    let db = Arc::new(RwLock::new(Database::new()));
    let listener = TcpListener::bind("127.0.0.1:6000").unwrap();

    info!("Socket bound");

    for stream in listener.incoming() {
        // info!("connection established, spawning new thread");
        let db2 = db.clone();
        match stream {
            Ok(stream) => {
                thread::spawn(move || {
                    handle_client(stream, db2)
                    });
            },
            Err(e) => {}
        }
    }

    info!("Goodbye forever.");
}

fn handle_client(mut stream: TcpStream, mut db: DB ) {
    info!("Starting new client thread");

    let mut buf = BufStream::new(stream);

    let mut buffer = String::new();
    for line in buf.lines() {
        let l = line.unwrap();
        println!("Line: {}", l);
    }

}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate icecore;

use getopts::{optopt, optflag, getopts, usage};
use std::os;

use icecore::data::FileStore;
use icecore::ic::Icecore;

fn demo(ic: &mut Icecore) {
    let id = ic.insert(String::from_str("foo"));
    println!("new document: id={}", id);
    println!("get({}, None) -> {}", id, ic.get(id, None));

    ic.update(id, String::from_str("bar"));
    println!("get({}, None) -> {}", id, ic.get(id, None));
    println!("get({}, 1) -> {}", id, ic.get(id, Some(0u64)));

    ic.dump();
}

fn main() {
    let args: Vec<String> = os::args();

    let store = box FileStore::new(String::from_str("_documents"));
    let mut ic = Icecore::new(
        Path::new("_documents"),
        store,
    );

    ic.load();

    match args[1].as_slice() {
        "insert" => {
            let opts = [
                optopt("d", "data", "Data to insert into the database", "DATA"),
                optflag("h", "help", "print this help message and exit"),
            ];

            let matches = match getopts(args.tail(), &opts) {
                Ok(m) => m,
                Err(_) => panic!("{}", usage("Insert data in the data store", &opts)),
            };

            if matches.opt_present("h") {
                println!("{}", usage("Insert data in the data store", &opts));
                return;
            }

            let data = matches.opt_str("d").unwrap();
            ic.insert(data);
        },
        "get" => {
            let opts = [
                optopt("v", "version", "Requested document version", "VERSION"),
            ];
            let matches = match getopts(args.slice_from(2), &opts) {
                Ok(m) => m,
                Err(_) => panic!(usage("Get document by id", &opts)),
            };
            let id = from_str::<u64>(args[2].as_slice()).unwrap();
            let version: Option<u64> = match matches.opt_str("v") {
                Some(v) => Some(from_str::<u64>(v.as_slice()).unwrap()),
                None => None,
            };
            println!("getting document id={} version={}", id, version);
            let data = ic.get(id, version);
            println!("{}", data);
        },
        "demo" => {
            demo(&mut ic);
        },
        _ => {
            println!("Command not found.");
        }
    }

    ic.dump();
}
<commit_msg>Added update command<commit_after>extern crate getopts;
extern crate icecore;

use getopts::{optopt, optflag, getopts, usage};
use std::os;

use icecore::data::FileStore;
use icecore::ic::Icecore;

fn demo(ic: &mut Icecore) {
    let id = ic.insert(String::from_str("foo"));
    println!("new document: id={}", id);
    println!("get({}, None) -> {}", id, ic.get(id, None));

    ic.update(id, String::from_str("bar"));
    println!("get({}, None) -> {}", id, ic.get(id, None));
    println!("get({}, 1) -> {}", id, ic.get(id, Some(0u64)));

    ic.dump();
}

fn main() {
    let args: Vec<String> = os::args();

    let store = box FileStore::new(String::from_str("_documents"));
    let mut ic = Icecore::new(
        Path::new("_documents"),
        store,
    );

    ic.load();

    if args.len() < 2 {
        panic!("not enough arguments");
    }

    match args[1].as_slice() {
        "insert" => {
            let opts = [
                optopt("d", "data", "Data to write", "DATA"),
                optflag("h", "help", "print this help message and exit"),
            ];
            let matches = match getopts(args.slice_from(1), &opts) {
                Ok(m) => m,
                Err(_) => panic!(usage("Insert new document", &opts)),
            };

            let data = matches.opt_str("d").unwrap();
            ic.insert(data);
        },
        "get" => {
            let opts = [
                optopt("v", "version", "Requested document version", "VERSION"),
            ];
            let matches = match getopts(args.slice_from(2), &opts) {
                Ok(m) => m,
                Err(_) => panic!(usage("Get document by id", &opts)),
            };

            let id = from_str::<u64>(args[2].as_slice()).unwrap();
            let version: Option<u64> = match matches.opt_str("v") {
                Some(v) => Some(from_str::<u64>(v.as_slice()).unwrap()),
                None => None,
            };
            println!("getting document id={} version={}", id, version);
            let data = ic.get(id, version);
            println!("{}", data);
        },
        "update" => {
            let opts = [
                optopt("d", "data", "Data to write", "DATA"),
            ];
            let matches = match getopts(args.slice_from(2), &opts) {
                Ok(m) => m,
                Err(_) => panic!(usage("", &opts)),
            };

            let id = from_str::<u64>(args[2].as_slice()).unwrap();
            let data = matches.opt_str("d").unwrap();
            println!("updating document id={}", id);
            ic.update(id, data);
        },
        "demo" => {
            demo(&mut ic);
        },
        _ => {
            println!("Command not found.");
        }
    }

    ic.dump();
}
<|endoftext|>


<commit_before>//#![feature(convert)]

//extern crate std;
extern crate libc;

use std::process::Command;
use std::str;
use std::option::Option;
use std::collections::BTreeSet;
use libc::{execvp, perror};
use std::ptr;
use std::env;
use std::path::PathBuf;
use std::ffi::CString;
use std::ffi::CStr;

fn detached_session_number(line: &str) -> Option<usize> {
    if line.ends_with("(attached)") {
        None
    } else {
        line.split(':').next().and_then(|s| s.parse().ok() )
    }
}

fn detached_sessions(output: &str) -> BTreeSet<usize> {
    output.lines().filter_map(|line| {
            detached_session_number(line)
    }).collect()
}

fn exec_program(program: &str, args: &[&str]) {
    // Each of these CStrings has to outlive pointers to it. Sadly,
    // the rust compiler doesn't scream when they don't (see
    // http://is.gd/nS339k), so we better make damn sure that the args
    // will stick around.
    let c_program_as_cstring = CString::new(program.bytes().collect::<Vec<u8>>()).unwrap();
    let c_program = c_program_as_cstring.as_ptr();

    let args_as_cstring = args.iter().map(|arg| CString::new(arg.bytes().collect::<Vec<u8>>()).unwrap()).collect::<Vec<CString>>();
    let mut c_args = args_as_cstring.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
    c_args.push(ptr::null());

    unsafe {
        execvp(c_program, c_args.as_mut_ptr());
        perror(CString::new("execvp".bytes().collect::<Vec<u8>>()).unwrap().as_ptr());
        println!("execvp of {:?} failed", CStr::from_ptr(c_program).to_bytes_with_nul());
    }
    panic!("Oh noes, couldn't execvp.");
}

fn prepare_environment() {
    if let Some(path) = env::var_os("PATH") {
        let mut paths = env::split_paths(&path).collect::<Vec<_>>();
        paths.push(PathBuf::from("/usr/local/bin"));
        let new_path = env::join_paths(paths.iter()).unwrap();
        env::set_var("PATH", &new_path);
    } else {
        let new_path = env::join_paths(["/usr/bin", "/bin", "/usr/local/bin"].iter().map(|p| PathBuf::from(p)).collect::<Vec<_>>()).unwrap();
        env::set_var("PATH", &new_path);
    }
}

fn start_server() {
    Command::new("tmux").arg("start-server").status().ok()
        .expect("Could not start tmux server: it exited with an error status.");
}

fn main() {
    prepare_environment();

    start_server();
    let session_output = Command::new("tmux").arg("list-sessions").output().ok()
        .expect("Running list-sessions command exited with an error status");

    let output = str::from_utf8(&session_output.stdout).ok()
        .expect("Could not read the (expected) utf-8 from tmux");
    let sessions = detached_sessions(output);

    match sessions.iter().next() {
        Some(n) => {
            let my_str = n.to_string();
            let session = my_str.as_ref();
            let mut args: Vec<&str> = vec!["tmux", "attach-session", "-t"];
            args.push(session);
            exec_program("tmux", args.as_slice());
        }
        _ => { exec_program("tmux", ["tmux"].as_ref()); }
    }
}

#[test]
fn test_session_number_with_numbers(){
    match detached_session_number("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]") {
        Some(11) => (),
        Some(n) => panic!(format!("Should have returned 11, got {}!", n)),
        None => panic!("Should have returned something, got nothing"),
    }
}

#[test]
fn test_session_number_with_strings(){
    match detached_session_number("oink: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]") {
        Some(n) => panic!(format!("Should have returned None, got {}!", n)),
        None => ()
    }
}

#[test]
fn test_session_number_with_attached_session(){
    match detached_session_number("1: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)") {
        Some(n) => panic!(format!("Should have returned None, got {}!", n)),
        None => ()
    }
}

#[test]
fn test_detached_sessions() {
    let set = detached_sessions("3: foo (attached)\n2: bar\n15: oink\n4: baz (attached)\nfoo: baz");
    // attached sessions:
    assert!(!set.contains(&3));
    assert!(!set.contains(&4));

    // detached sessions should be present:
    assert!(set.contains(&15));
    assert!(set.contains(&2));

    // missing session:
    assert!(!set.contains(&1));
}
<commit_msg>Make "tmux" a constant<commit_after>//#![feature(convert)]

//extern crate std;
extern crate libc;

use std::process::Command;
use std::str;
use std::option::Option;
use std::collections::BTreeSet;
use libc::{execvp, perror};
use std::ptr;
use std::env;
use std::path::PathBuf;
use std::ffi::CString;
use std::ffi::CStr;

const PROGRAM: &'static str = "tmux";

fn detached_session_number(line: &str) -> Option<usize> {
    if line.ends_with("(attached)") {
        None
    } else {
        line.split(':').next().and_then(|s| s.parse().ok() )
    }
}

fn detached_sessions(output: &str) -> BTreeSet<usize> {
    output.lines().filter_map(|line| {
            detached_session_number(line)
    }).collect()
}

fn exec_program(program: &str, args: &[&str]) {
    // Each of these CStrings has to outlive pointers to it. Sadly,
    // the rust compiler doesn't scream when they don't (see
    // http://is.gd/nS339k), so we better make damn sure that the args
    // will stick around.
    let c_program_as_cstring = CString::new(program.bytes().collect::<Vec<u8>>()).unwrap();
    let c_program = c_program_as_cstring.as_ptr();

    let args_as_cstring = args.iter().map(|arg| CString::new(arg.bytes().collect::<Vec<u8>>()).unwrap()).collect::<Vec<CString>>();
    let mut c_args = args_as_cstring.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
    c_args.push(ptr::null());

    unsafe {
        execvp(c_program, c_args.as_mut_ptr());
        perror(CString::new("execvp".bytes().collect::<Vec<u8>>()).unwrap().as_ptr());
        println!("execvp of {:?} failed", CStr::from_ptr(c_program).to_bytes_with_nul());
    }
    panic!("Oh noes, couldn't execvp.");
}

fn prepare_environment() {
    if let Some(path) = env::var_os("PATH") {
        let mut paths = env::split_paths(&path).collect::<Vec<_>>();
        paths.push(PathBuf::from("/usr/local/bin"));
        let new_path = env::join_paths(paths.iter()).unwrap();
        env::set_var("PATH", &new_path);
    } else {
        let new_path = env::join_paths(["/usr/bin", "/bin", "/usr/local/bin"].iter().map(|p| PathBuf::from(p)).collect::<Vec<_>>()).unwrap();
        env::set_var("PATH", &new_path);
    }
}

fn start_server() {
    Command::new(PROGRAM).arg("start-server").status().ok()
        .expect("Could not start tmux server: it exited with an error status.");
}

fn main() {
    prepare_environment();

    start_server();
    let session_output = Command::new(PROGRAM).arg("list-sessions").output().ok()
        .expect("Running list-sessions command exited with an error status");

    let output = str::from_utf8(&session_output.stdout).ok()
        .expect("Could not read the (expected) utf-8 from tmux");
    let sessions = detached_sessions(output);

    match sessions.iter().next() {
        Some(n) => {
            let my_str = n.to_string();
            let session = my_str.as_ref();
            let mut args: Vec<&str> = vec![PROGRAM, "attach-session", "-t"];
            args.push(session);
            exec_program(PROGRAM, &args);
        }
        _ => { exec_program(PROGRAM, [PROGRAM].as_ref()); }
    }
}

#[test]
fn test_session_number_with_numbers(){
    match detached_session_number("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]") {
        Some(11) => (),
        Some(n) => panic!(format!("Should have returned 11, got {}!", n)),
        None => panic!("Should have returned something, got nothing"),
    }
}

#[test]
fn test_session_number_with_strings(){
    match detached_session_number("oink: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]") {
        Some(n) => panic!(format!("Should have returned None, got {}!", n)),
        None => ()
    }
}

#[test]
fn test_session_number_with_attached_session(){
    match detached_session_number("1: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)") {
        Some(n) => panic!(format!("Should have returned None, got {}!", n)),
        None => ()
    }
}

#[test]
fn test_detached_sessions() {
    let set = detached_sessions("3: foo (attached)\n2: bar\n15: oink\n4: baz (attached)\nfoo: baz");
    // attached sessions:
    assert!(!set.contains(&3));
    assert!(!set.contains(&4));

    // detached sessions should be present:
    assert!(set.contains(&15));
    assert!(set.contains(&2));

    // missing session:
    assert!(!set.contains(&1));
}
<|endoftext|>