<commit_before>#[macro_use]
extern crate wayland_client;

extern crate tempfile;

extern crate byteorder;
extern crate image;
extern crate dbus;

use std::env;
use std::process::exit;
use image::{load_from_memory, open};
use std::mem::transmute;
use std::os::unix::io::AsRawFd;
use std::io::Write;

use wayland_client::wayland::get_display;
use wayland_client::wayland::compositor::{WlCompositor, WlSurface};
use wayland_client::wayland::shell::WlShell;
use wayland_client::wayland::shm::{WlBuffer, WlShm, WlShmFormat};
use wayland_client::wayland::seat::{WlSeat, WlPointerEvent};
use wayland_client::{EventIterator, Proxy};

use byteorder::{NativeEndian, WriteBytesExt};

use dbus::{Connection, Message, MessageItem, BusType};

wayland_env!(WaylandEnv,
             compositor: WlCompositor,
             shell: WlShell,
             shm: WlShm,
             seat: WlSeat
);

const CURSOR: &'static [u8; 656] = include_bytes!("../assets/arrow.png");

// DBus wait time
const DBUS_WAIT_TIME: i32 = 2000;

type BufferResult = Result<WlBuffer, ()>;

#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
/// Holds the bytes to represent a colored background.
/// To be written into a wayland surface.
pub struct Color(pub [u8; 4]);

impl Color {
    /// Generate a new color out of a u32.
    /// E.G: 0xFFFFFF
    pub fn from_u32(color: u32) -> Self {
        unsafe { Color(transmute(color)) }
    }

    pub fn as_u32(&self) -> u32 {
        unsafe { transmute(self.0)}
    }
}

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() < 1 {
        println!("Please supply either a file path or a color (written in hex)");
        exit(1);
    }
    let input = &args[1];

    let (display, iter) = get_display()
        .expect("Unable to connect to a wayland compositor");
    let (env, evt_iter) = WaylandEnv::init(display, iter);
    let compositor = env.compositor.as_ref().map(|o| &o.0).unwrap();
    let shell = env.shell.as_ref().map(|o| &o.0).unwrap();
    let mut background_surface = compositor.create_surface();
    let shell_surface = shell.get_shell_surface(&background_surface);
    shell_surface.set_class("Background".into());
    // TODO Actually give it the path or something idk
    shell_surface.set_title(input.clone());

    // We need to hold on to this buffer, this holds the background image!
    let _background_buffer = if let Ok(color) = input.parse::<u32>() {
        let color = Color::from_u32(color);
        generate_solid_background(color, &mut background_surface, &env)
    } else {
        generate_image_background(input.as_str(), &mut background_surface, &env)
    }.expect("could not generate image");

    background_surface.commit();
    background_surface.set_buffer_scale(1);
    let mut cursor_surface = compositor.create_surface();
    let _cursor_buffer = self::cursor_surface(&mut cursor_surface, &env);
    main_background_loop(background_surface, cursor_surface, evt_iter, &env);
}

fn rgba_conversion(num: u8, third_num: u32) -> u8 {
    let big_num = num as u32;
    ((big_num * third_num) / 255) as u8
}

fn get_screen_resolution(con: Connection) -> (i32, i32) {
    let screens_msg = Message::new_method_call("org.way-cooler",
                                               "/org/way_cooler/Screen",
                                               "org.way_cooler.Screen",
                                               "List")
        .expect("Could not construct message -- is Way Cooler running?");
    let screen_r = con.send_with_reply_and_block(screens_msg, DBUS_WAIT_TIME)
        .expect("Could not talk to Way Cooler -- is Way Cooler running?");
    let screen_r = &screen_r.get_items()[0];
    let output_id = match screen_r {
        &MessageItem::Array(ref items, _) => {
            match items[0] {
                MessageItem::Str(ref string) => string.clone(),
                _ => panic!("Array didn't contain output id")
            }
        }
        _ => panic!("Wrong type from Screen")
    };
    let res_msg = Message::new_method_call("org.way-cooler",
                                           "/org/way_cooler/Screen",
                                           "org.way_cooler.Screen",
                                           "Resolution")
        .expect("Could not construct message -- is Way Cooler running?")
        .append(MessageItem::Str(output_id));
    let reply: MessageItem = con.send_with_reply_and_block(res_msg, DBUS_WAIT_TIME)
        .expect("Could not talk to Way Cooler -- is Way Cooler running?")
        .get1()
        .expect("Way Cooler returned an unexpected value");
    match reply {
        MessageItem::Struct(items) => {
            let (width, height) = (
                (&items[0]).inner::<u32>()
                    .expect("Way Cooler returned an unexpected value"),
                (&items[1]).inner::<u32>()
                    .expect("Way Cooler returned an unexpected value")
            );
            println!("{:?}, {:?}", width, height);
            (width as i32, height as i32)
        },
        _ => panic!("Colud not get resolution of screen")
    }
}

/// Given a solid color, writes bytes associated with that color to
/// a special Wayland surface which is then rendered as a background for Way Cooler.
fn generate_solid_background(color: Color, background_surface: &mut WlSurface,
                                 env: &WaylandEnv) -> BufferResult {
    // Get shortcuts to the globals.
    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();

    // Create the surface we are going to write into
    let mut tmp = tempfile::tempfile().ok().expect("Unable to create a tempfile.");

    // Calculate how big the buffer needs to be from the output resolution
    // TODO Get the output size from way cooler somehow...
    //let resolution = output.get_resolution()
    //    .expect("Couldn't get output resolution");
    //let (width, height) = (resolution.w as i32, resolution.h as i32);
    let width = 16; let height = 9;
    let size = (width * height) as i32;

    // Write in the color coding to the surface
    for _ in 0..size {
        unsafe {
            tmp.write_u32::<NativeEndian>(transmute(color.0))
                .expect("Could not write to file")
        }
    }
    tmp.flush()
        .expect("Could not flush buffer");

    // Create the buffer that is mem-mapped to the temp file descriptor
    let pool = shm.create_pool(tmp.as_raw_fd(), size);
    let background_buffer = pool.create_buffer(0, width, height, width, WlShmFormat::Argb8888);
    // Tell Way Cooler not to set put this in the tree, treat as background

    // Attach the buffer to the surface
    background_surface.attach(Some(&background_buffer), 0, 0);
    Ok(background_buffer)
}

/// Given the data from an image, writes it to a special Wayland surface
/// which is then rendered as a background for Way Cooler.
fn generate_image_background(path: &str, background_surface: &mut WlSurface,
                             env: &WaylandEnv) -> BufferResult {
    // TODO support more formats, split into separate function
    let image = open(path)
        .unwrap_or_else(|_| {
            println!("Could not open image file \"{:?}\"", path);
            ::std::process::exit(1);
        });
    /*let image = load_from_memory(CURSOR)
        .expect("Could not read cursor data, report to maintainer!");*/
    let mut image = image.to_rgba();
    let width = image.width();
    let height = image.height();
    let stride = width * 4;
    let size = stride * height;
    // TODO Split this into its own function
    {
        let pixels = image.enumerate_pixels_mut();
        for (_x, _y, pixel) in pixels {
            let alpha = pixel[3] as u32;
            pixel[0] = rgba_conversion(pixel[0], alpha);
            pixel[1] = rgba_conversion(pixel[1], alpha);
            pixel[2] = rgba_conversion(pixel[2], alpha);

            let tmp = pixel[2];
            pixel[2] = pixel[0];
            pixel[0] = tmp;
        }
    }
    let vec = image.into_vec();
    let mut tmp = tempfile::NamedTempFile::new().expect("Unable to create a tempfile.");
    tmp.set_len(size as u64).expect("Could not truncate length of file");
    tmp.write_all(&*vec).unwrap();

    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();

    // Create the surface we are going to write into

    let pool = shm.create_pool(tmp.as_raw_fd(), size as i32);
    let background_buffer = pool.create_buffer(0, width as i32, height as i32, stride as i32, WlShmFormat::Argb8888);

    // Attach the buffer to the surface
    background_surface.attach(Some(&background_buffer), 0, 0);
    background_surface.damage(0, 0, width as i32, height as i32);
    Ok(background_buffer)
}

fn cursor_surface(cursor_surface: &mut WlSurface, env: &WaylandEnv) -> BufferResult {
    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();

    let image = load_from_memory(CURSOR)
        .expect("Could not read cursor data, report to maintainer!");
    let mut image = image.to_rgba();
    let width = image.width();
    let height = image.height();
    let stride = width * 4;
    let size = stride * height;
    {
        let pixels = image.enumerate_pixels_mut();
        for (_x, _y, pixel) in pixels {
            let alpha = pixel[3] as u32;
            pixel[0] = rgba_conversion(pixel[0], alpha);
            pixel[1] = rgba_conversion(pixel[1], alpha);
            pixel[2] = rgba_conversion(pixel[2], alpha);

            let tmp = pixel[2];
            pixel[2] = pixel[0];
            pixel[0] = tmp;
        }
    }
    let vec = image.into_vec();
    let mut tmp = tempfile::NamedTempFile::new().expect("Unable to create a tempfile.");
    tmp.set_len(size as u64).expect("Could not truncate length of file");
    tmp.write_all(&*vec).unwrap();
    let pool = shm.create_pool(tmp.as_raw_fd(), size as i32);
    let cursor_buffer = pool.create_buffer(0, width as i32, height as i32, stride as i32, WlShmFormat::Argb8888);
    cursor_surface.attach(Some(&cursor_buffer), 0, 0);
    Ok(cursor_buffer)
}

/// Main loop for rendering backgrounds.
/// Need to keep the surface alive, and update it if the
/// user wants to change the background.
#[allow(unused_variables)]
fn main_background_loop(background_surface: WlSurface, cursor_surface: WlSurface, mut event_iter: EventIterator, env: &WaylandEnv) {
    use wayland_client::wayland::WaylandProtocolEvent;
    use wayland_client::Event;
    let seat = env.seat.as_ref().map(|o| &o.0).unwrap();
    let mut pointer = seat.get_pointer();

    pointer.set_event_iterator(&event_iter);
    pointer.set_cursor(0, Some(&cursor_surface), 0, 0);
    background_surface.commit();
    event_iter.sync_roundtrip().unwrap();
    loop {
        for event in &mut event_iter {
            match event {
                Event::Wayland(wayland_event) => {
                    match wayland_event {
                        WaylandProtocolEvent::WlPointer(id, pointer_event) => {
                            match pointer_event {
                                WlPointerEvent::Enter(serial, background_surface, surface_x, surface_y) => {
                                    pointer.set_cursor(0, Some(&cursor_surface), 0, 0);
                                },
                                _ => {
                                }
                            }
                        },
                        _ => {/* unhandled events */}
                    }
                }
                _ => { /* unhandled events */ }
            }
        }
        event_iter.dispatch().expect("Connection with the compositor was lost.");
    }
}

#[test]
fn test_rgba_conversion() {
    assert_eq!(rgba_conversion(10, 254), 9);
    assert_eq!(rgba_conversion(2, 255), 2);
    assert_eq!(rgba_conversion(255, 500), 500);
}
<commit_msg>Added support to solid background real sized<commit_after>#[macro_use]
extern crate wayland_client;

extern crate tempfile;

extern crate byteorder;
extern crate image;
extern crate dbus;

use std::env;
use std::process::exit;
use image::{load_from_memory, open};
use std::mem::transmute;
use std::os::unix::io::AsRawFd;
use std::io::Write;

use wayland_client::wayland::get_display;
use wayland_client::wayland::compositor::{WlCompositor, WlSurface};
use wayland_client::wayland::shell::WlShell;
use wayland_client::wayland::shm::{WlBuffer, WlShm, WlShmFormat};
use wayland_client::wayland::seat::{WlSeat, WlPointerEvent};
use wayland_client::{EventIterator, Proxy};

use byteorder::{NativeEndian, WriteBytesExt};

use dbus::{Connection, Message, MessageItem, BusType};

wayland_env!(WaylandEnv,
             compositor: WlCompositor,
             shell: WlShell,
             shm: WlShm,
             seat: WlSeat
);

const CURSOR: &'static [u8; 656] = include_bytes!("../assets/arrow.png");

// DBus wait time
const DBUS_WAIT_TIME: i32 = 2000;

type BufferResult = Result<WlBuffer, ()>;

#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
/// Holds the bytes to represent a colored background.
/// To be written into a wayland surface.
pub struct Color(pub [u8; 4]);

impl Color {
    /// Generate a new color out of a u32.
    /// E.G: 0xFFFFFF
    pub fn from_u32(color: u32) -> Self {
        unsafe { Color(transmute(color)) }
    }

    pub fn as_u32(&self) -> u32 {
        unsafe { transmute(self.0)}
    }
}

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() < 1 {
        println!("Please supply either a file path or a color (written in hex)");
        exit(1);
    }
    let input = &args[1];

    let (display, iter) = get_display()
        .expect("Unable to connect to a wayland compositor");
    let (env, evt_iter) = WaylandEnv::init(display, iter);
    let compositor = env.compositor.as_ref().map(|o| &o.0).unwrap();
    let shell = env.shell.as_ref().map(|o| &o.0).unwrap();
    let mut background_surface = compositor.create_surface();
    let shell_surface = shell.get_shell_surface(&background_surface);
    shell_surface.set_class("Background".into());
    // TODO Actually give it the path or something idk
    shell_surface.set_title(input.clone());

    // We need to hold on to this buffer, this holds the background image!
    let _background_buffer = if let Ok(color) = input.parse::<u32>() {
        let color = Color::from_u32(color);
        generate_solid_background(color, &mut background_surface, &env)
    } else {
        generate_image_background(input.as_str(), &mut background_surface, &env)
    }.expect("could not generate image");

    background_surface.commit();
    background_surface.set_buffer_scale(1);
    let mut cursor_surface = compositor.create_surface();
    let _cursor_buffer = self::cursor_surface(&mut cursor_surface, &env);
    main_background_loop(background_surface, cursor_surface, evt_iter, &env);
}

fn rgba_conversion(num: u8, third_num: u32) -> u8 {
    let big_num = num as u32;
    ((big_num * third_num) / 255) as u8
}

fn get_screen_resolution(con: Connection) -> (i32, i32) {
    let screens_msg = Message::new_method_call("org.way-cooler",
                                               "/org/way_cooler/Screen",
                                               "org.way_cooler.Screen",
                                               "List")
        .expect("Could not construct message -- is Way Cooler running?");
    let screen_r = con.send_with_reply_and_block(screens_msg, DBUS_WAIT_TIME)
        .expect("Could not talk to Way Cooler -- is Way Cooler running?");
    let screen_r = &screen_r.get_items()[0];
    let output_id = match screen_r {
        &MessageItem::Array(ref items, _) => {
            match items[0] {
                MessageItem::Str(ref string) => string.clone(),
                _ => panic!("Array didn't contain output id")
            }
        }
        _ => panic!("Wrong type from Screen")
    };
    let res_msg = Message::new_method_call("org.way-cooler",
                                           "/org/way_cooler/Screen",
                                           "org.way_cooler.Screen",
                                           "Resolution")
        .expect("Could not construct message -- is Way Cooler running?")
        .append(MessageItem::Str(output_id));
    let reply: MessageItem = con.send_with_reply_and_block(res_msg, DBUS_WAIT_TIME)
        .expect("Could not talk to Way Cooler -- is Way Cooler running?")
        .get1()
        .expect("Way Cooler returned an unexpected value");
    match reply {
        MessageItem::Struct(items) => {
            let (width, height) = (
                (&items[0]).inner::<u32>()
                    .expect("Way Cooler returned an unexpected value"),
                (&items[1]).inner::<u32>()
                    .expect("Way Cooler returned an unexpected value")
            );
            println!("{:?}, {:?}", width, height);
            (width as i32, height as i32)
        },
        _ => panic!("Colud not get resolution of screen")
    }
}

/// Given a solid color, writes bytes associated with that color to
/// a special Wayland surface which is then rendered as a background for Way Cooler.
fn generate_solid_background(color: Color, background_surface: &mut WlSurface,
                                 env: &WaylandEnv) -> BufferResult {
    // Get shortcuts to the globals.
    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();

    // Create the surface we are going to write into
    let mut tmp = tempfile::tempfile().ok().expect("Unable to create a tempfile.");

    // Calculate how big the buffer needs to be from the output resolution
    let dbus_con = Connection::get_private(BusType::Session).unwrap();
    let (width, height) = get_screen_resolution(dbus_con);
    let size = (width * height) as i32;

    // Write in the color coding to the surface
    for _ in 0..size {
        unsafe {
            tmp.write_u32::<NativeEndian>(transmute(color.0))
                .expect("Could not write to file")
        }
    }
    tmp.flush()
        .expect("Could not flush buffer");

    // Create the buffer that is mem-mapped to the temp file descriptor
    let pool = shm.create_pool(tmp.as_raw_fd(), size);
    let background_buffer = pool.create_buffer(0, width, height, width, WlShmFormat::Argb8888);
    // Tell Way Cooler not to set put this in the tree, treat as background

    // Attach the buffer to the surface
    background_surface.attach(Some(&background_buffer), 0, 0);
    Ok(background_buffer)
}

/// Given the data from an image, writes it to a special Wayland surface
/// which is then rendered as a background for Way Cooler.
fn generate_image_background(path: &str, background_surface: &mut WlSurface,
                             env: &WaylandEnv) -> BufferResult {
    // TODO support more formats, split into separate function
    let image = open(path)
        .unwrap_or_else(|_| {
            println!("Could not open image file \"{:?}\"", path);
            ::std::process::exit(1);
        });
    /*let image = load_from_memory(CURSOR)
        .expect("Could not read cursor data, report to maintainer!");*/
    let mut image = image.to_rgba();
    let width = image.width();
    let height = image.height();
    let stride = width * 4;
    let size = stride * height;
    // TODO Split this into its own function
    {
        let pixels = image.enumerate_pixels_mut();
        for (_x, _y, pixel) in pixels {
            let alpha = pixel[3] as u32;
            pixel[0] = rgba_conversion(pixel[0], alpha);
            pixel[1] = rgba_conversion(pixel[1], alpha);
            pixel[2] = rgba_conversion(pixel[2], alpha);

            let tmp = pixel[2];
            pixel[2] = pixel[0];
            pixel[0] = tmp;
        }
    }
    let vec = image.into_vec();
    let mut tmp = tempfile::NamedTempFile::new().expect("Unable to create a tempfile.");
    tmp.set_len(size as u64).expect("Could not truncate length of file");
    tmp.write_all(&*vec).unwrap();

    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();

    // Create the surface we are going to write into

    let pool = shm.create_pool(tmp.as_raw_fd(), size as i32);
    let background_buffer = pool.create_buffer(0, width as i32, height as i32, stride as i32, WlShmFormat::Argb8888);

    // Attach the buffer to the surface
    background_surface.attach(Some(&background_buffer), 0, 0);
    background_surface.damage(0, 0, width as i32, height as i32);
    Ok(background_buffer)
}

fn cursor_surface(cursor_surface: &mut WlSurface, env: &WaylandEnv) -> BufferResult {
    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();

    let image = load_from_memory(CURSOR)
        .expect("Could not read cursor data, report to maintainer!");
    let mut image = image.to_rgba();
    let width = image.width();
    let height = image.height();
    let stride = width * 4;
    let size = stride * height;
    {
        let pixels = image.enumerate_pixels_mut();
        for (_x, _y, pixel) in pixels {
            let alpha = pixel[3] as u32;
            pixel[0] = rgba_conversion(pixel[0], alpha);
            pixel[1] = rgba_conversion(pixel[1], alpha);
            pixel[2] = rgba_conversion(pixel[2], alpha);

            let tmp = pixel[2];
            pixel[2] = pixel[0];
            pixel[0] = tmp;
        }
    }
    let vec = image.into_vec();
    let mut tmp = tempfile::NamedTempFile::new().expect("Unable to create a tempfile.");
    tmp.set_len(size as u64).expect("Could not truncate length of file");
    tmp.write_all(&*vec).unwrap();
    let pool = shm.create_pool(tmp.as_raw_fd(), size as i32);
    let cursor_buffer = pool.create_buffer(0, width as i32, height as i32, stride as i32, WlShmFormat::Argb8888);
    cursor_surface.attach(Some(&cursor_buffer), 0, 0);
    Ok(cursor_buffer)
}

/// Main loop for rendering backgrounds.
/// Need to keep the surface alive, and update it if the
/// user wants to change the background.
#[allow(unused_variables)]
fn main_background_loop(background_surface: WlSurface, cursor_surface: WlSurface, mut event_iter: EventIterator, env: &WaylandEnv) {
    use wayland_client::wayland::WaylandProtocolEvent;
    use wayland_client::Event;
    let seat = env.seat.as_ref().map(|o| &o.0).unwrap();
    let mut pointer = seat.get_pointer();

    pointer.set_event_iterator(&event_iter);
    pointer.set_cursor(0, Some(&cursor_surface), 0, 0);
    background_surface.commit();
    event_iter.sync_roundtrip().unwrap();
    loop {
        for event in &mut event_iter {
            match event {
                Event::Wayland(wayland_event) => {
                    match wayland_event {
                        WaylandProtocolEvent::WlPointer(id, pointer_event) => {
                            match pointer_event {
                                WlPointerEvent::Enter(serial, background_surface, surface_x, surface_y) => {
                                    pointer.set_cursor(0, Some(&cursor_surface), 0, 0);
                                },
                                _ => {
                                }
                            }
                        },
                        _ => {/* unhandled events */}
                    }
                }
                _ => { /* unhandled events */ }
            }
        }
        event_iter.dispatch().expect("Connection with the compositor was lost.");
    }
}

#[test]
fn test_rgba_conversion() {
    assert_eq!(rgba_conversion(10, 254), 9);
    assert_eq!(rgba_conversion(2, 255), 2);
    assert_eq!(rgba_conversion(255, 500), 500);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate toml;
extern crate semver;
extern crate term;

use std::io::{Read, Write};
use std::fs::{File, OpenOptions};
use std::path::Path;
use std::process::Command;
use semver::Version;
use cr_result::CrResult;
use config::Config;
use cargo_proj::CargoProj;
use utils::check_output;

mod git;
mod cr_result;
mod version_kind;
mod config;
mod cargo_proj;
mod cargo;
mod utils;

fn main() {
    set_stdout_stderr_colors();

    let mut exit_code = 0;
    execute().unwrap_or_else(|err| {
        let mut stderr = term::stderr().unwrap();
        writeln!(stderr, "{}", err).unwrap();
        exit_code = 1;
    });

    reset_stdout_stderr();
    std::process::exit(exit_code);
}

fn execute() -> CrResult<()> {
    let mut stdout = term::stdout().unwrap();

    let config = try!(Config::from_command_args());
    let mut cargo_proj = try!(CargoProj::find(&config.start_dir));

    try!(std::env::set_current_dir(try!(cargo_proj.root_dir())));

    try!(writeln!(stdout, "Checking git state ..."));
    try!(git::check_clean_state());

    let curr_version = cargo_proj.version().clone();
    let new_version = config.version_kind.increment(&curr_version);
    try!(cargo_proj.write_version(&new_version));

    try!(writeln!(stdout, "Building release ..."));
    try!(cargo::build_release());

    try!(writeln!(stdout, "Testing ..."));
    try!(cargo::test());

    if let Some(changelog) = cargo_proj.changelog() {
        try!(writeln!(stdout, "Updating changelog ..."));
        try!(update_changelog(changelog, &new_version));
    }

    try!(writeln!(stdout, "Creating git commit ..."));
    try!(git::add_update());
    try!(git::commit(&commit_message(&cargo_proj)));
    try!(git::tag(&tag_name(&cargo_proj)));

    try!(writeln!(stdout, "Pushing git changes ..."));
    try!(git::push());

    try!(writeln!(stdout, "Publishing to crates.io ..."));
    try!(cargo::publish());

    Ok(())
}

/// Adds `new_version` at the top of the `changelog` and opens
/// `changelog` in the editor specified by `CARGO_RELEASE_EDITOR` (default: gvim).
fn update_changelog(changelog: &Path, new_version: &Version) -> CrResult<()> {
    let contents = {
        let mut file = try!(File::open(changelog));
        let mut contents = String::new();
        try!(file.read_to_string(&mut contents));
        contents
    };

    let contents = format!("{}\n\n{}", new_version, contents);
    {
        let mut file = try!(OpenOptions::new()
            .truncate(true)
            .read(true)
            .write(true)
            .open(changelog));

        try!(file.write_all(contents.as_bytes()));
    }

    let editor = std::env::var("CARGO_RELEASE_EDITOR").unwrap_or("gvim".to_string());
    let output = try!(Command::new(editor)
        .arg(changelog)
        .output());

    try!(check_output(&output));
    Ok(())
}

fn commit_message(proj: &CargoProj) -> String {
    format!("{} {}", proj.name(), proj.version())
}

fn tag_name(proj: &CargoProj) -> String {
    format!("{}-{}", proj.name(), proj.version())
}

fn set_stdout_stderr_colors() {
    let mut stdout = term::stdout().unwrap();
    stdout.fg(term::color::GREEN).unwrap();

    let mut stderr = term::stderr().unwrap();
    stderr.fg(term::color::RED).unwrap();
}

fn reset_stdout_stderr() {
    let mut stdout = term::stdout().unwrap();
    stdout.reset().unwrap();

    let mut stderr = term::stderr().unwrap();
    stderr.reset().unwrap();
}
<commit_msg>Call tests before modifying the  and bulding the release<commit_after>#[macro_use]
extern crate clap;
extern crate toml;
extern crate semver;
extern crate term;

use std::io::{Read, Write};
use std::fs::{File, OpenOptions};
use std::path::Path;
use std::process::Command;
use semver::Version;
use cr_result::CrResult;
use config::Config;
use cargo_proj::CargoProj;
use utils::check_output;

mod git;
mod cr_result;
mod version_kind;
mod config;
mod cargo_proj;
mod cargo;
mod utils;

fn main() {
    set_stdout_stderr_colors();

    let mut exit_code = 0;
    execute().unwrap_or_else(|err| {
        let mut stderr = term::stderr().unwrap();
        writeln!(stderr, "{}", err).unwrap();
        exit_code = 1;
    });

    reset_stdout_stderr();
    std::process::exit(exit_code);
}

fn execute() -> CrResult<()> {
    let mut stdout = term::stdout().unwrap();

    let config = try!(Config::from_command_args());
    let mut cargo_proj = try!(CargoProj::find(&config.start_dir));

    try!(std::env::set_current_dir(try!(cargo_proj.root_dir())));

    try!(writeln!(stdout, "Checking git state ..."));
    try!(git::check_clean_state());

    try!(writeln!(stdout, "Testing ..."));
    try!(cargo::test());

    let curr_version = cargo_proj.version().clone();
    let new_version = config.version_kind.increment(&curr_version);
    try!(cargo_proj.write_version(&new_version));

    try!(writeln!(stdout, "Building release ..."));
    try!(cargo::build_release());

    if let Some(changelog) = cargo_proj.changelog() {
        try!(writeln!(stdout, "Updating changelog ..."));
        try!(update_changelog(changelog, &new_version));
    }

    try!(writeln!(stdout, "Creating git commit ..."));
    try!(git::add_update());
    try!(git::commit(&commit_message(&cargo_proj)));
    try!(git::tag(&tag_name(&cargo_proj)));

    try!(writeln!(stdout, "Pushing git changes ..."));
    try!(git::push());

    try!(writeln!(stdout, "Publishing to crates.io ..."));
    try!(cargo::publish());

    Ok(())
}

/// Adds `new_version` at the top of the `changelog` and opens
/// `changelog` in the editor specified by `CARGO_RELEASE_EDITOR` (default: gvim).
fn update_changelog(changelog: &Path, new_version: &Version) -> CrResult<()> {
    let contents = {
        let mut file = try!(File::open(changelog));
        let mut contents = String::new();
        try!(file.read_to_string(&mut contents));
        contents
    };

    let contents = format!("{}\n\n{}", new_version, contents);
    {
        let mut file = try!(OpenOptions::new()
            .truncate(true)
            .read(true)
            .write(true)
            .open(changelog));

        try!(file.write_all(contents.as_bytes()));
    }

    let editor = std::env::var("CARGO_RELEASE_EDITOR").unwrap_or("gvim".to_string());
    let output = try!(Command::new(editor)
        .arg(changelog)
        .output());

    try!(check_output(&output));
    Ok(())
}

fn commit_message(proj: &CargoProj) -> String {
    format!("{} {}", proj.name(), proj.version())
}

fn tag_name(proj: &CargoProj) -> String {
    format!("{}-{}", proj.name(), proj.version())
}

fn set_stdout_stderr_colors() {
    let mut stdout = term::stdout().unwrap();
    stdout.fg(term::color::GREEN).unwrap();

    let mut stderr = term::stderr().unwrap();
    stderr.fg(term::color::RED).unwrap();
}

fn reset_stdout_stderr() {
    let mut stdout = term::stdout().unwrap();
    stdout.reset().unwrap();

    let mut stderr = term::stderr().unwrap();
    stderr.reset().unwrap();
}
<|endoftext|>


<commit_before>extern crate base64;
extern crate docopt;
extern crate rustc_serialize;

use std::error::Error;
use std::fs::File;
use std::io::{self, Write};
use std::path::Path;
use std::str;

use docopt::Docopt;

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

// MAGIC (!) buf size divisible by 3 for encode and by 4 for decode
const BUF_SIZE: usize = 4092;

const USAGE: &'static str = "
Base64 encode or decode FILE, or standard input, to standard output.

Usage: base64 [options] [<file>]
       base64 (--help | --version)

Options:
  -d --decode   decode data
  -h --help     display this help and exit
  --version     output version information and exit
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_file: String,
    flag_decode: bool,
    flag_help: bool,
    flag_version: bool,
}

fn encode(file: &mut io::Read) {
    let mut buf = [0u8; BUF_SIZE];
    let mut out_buf = [0u8; BUF_SIZE * 4 / 3];
    let mut stdout = io::stdout();

    loop {
        match file.read(&mut buf[..]) {
            Ok(count) => {
                if count == 0 {
                    print!("\n");
                    break;
                }
                let encode_count = base64::encode(
                    &buf[..count], &mut out_buf);
                stdout.write(&out_buf[..encode_count]).unwrap();
            },
            Err(err) => panic!(err),
        }
    }
}

fn decode(file: &mut io::Read) {
    let mut buf = [0u8; BUF_SIZE];
    let mut out_buf = [0u8; BUF_SIZE * 3 / 4];
    let mut stdout = io::stdout();
    let mut stderr = io::stderr();

    loop {
        match file.read(&mut buf[..]) {
            Ok(count) => {
                if count == 0 {
                     break;
                }
                match base64::decode(&buf[..count], &mut out_buf) {
                    Ok(count) => {
                        stdout.write(&mut out_buf[..count]).unwrap();
                    },
                    Err(msg) => {
                        stderr.write(msg.as_bytes()).unwrap();

                    },
                }
            },
            Err(err) => panic!(err),
        }
    }
}

fn process(file: &mut io::Read, is_decode: bool) {
    if is_decode {
        decode(file);
    } else {
        encode(file);
    }
}

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

    if args.flag_version {
        println!("base64 v{}", VERSION);
        return;
    }

    if args.arg_file != "" {
        let path = Path::new(&args.arg_file);
        let mut file = match File::open(&path) {
            Err(why) => panic!("couldn't open {}: {}",
                               path.display(), why.description()),
            Ok(file) => file,
        };
        process(&mut file, args.flag_decode);
    } else {
        process(&mut io::stdin(), args.flag_decode);
    }
}
<commit_msg>Add new flag for output wrapping<commit_after>extern crate base64;
extern crate docopt;
extern crate rustc_serialize;

use std::error::Error;
use std::fs::File;
use std::io::{self, Write};
use std::path::Path;
use std::str;

use docopt::Docopt;

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

// MAGIC (!) buf size divisible by 3 for encode and by 4 for decode
const BUF_SIZE: usize = 4092;

const USAGE: &'static str = "
Base64 encode or decode FILE, or standard input, to standard output.

Usage: base64 [options] [<file>]
       base64 (--help | --version)

Options:
  -d --decode      decode data
  -h --help        display this help and exit
  -w --wrap COLS   wrap encoded lines after COLS character (default 76).
                   Use 0 to disable line wrapping
  --version     output version information and exit
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_file: String,
    flag_decode: bool,
    flag_help: bool,
    flag_version: bool,
    flag_wrap: Option<usize>,
}

struct WrapedOutput<'a> {
    out: &'a mut io::Write,
    wrap: usize,
}

impl<'a> Write for WrapedOutput<'a> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let buf_len = buf.len();
        let mut writed: usize = 0;

        loop {
            let bound = if self.wrap == 0 {
                buf_len
            } else if (writed + self.wrap) >= buf_len {
                buf_len
            } else {
                writed + self.wrap
            };

            writed += try!(self.out.write(&buf[writed..bound]));

            if writed >= buf_len {
                return Ok(writed);
            }
            try!(self.out.write(b"\n"));
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        self.out.flush()
    }
}

fn encode(file: &mut io::Read, wrap: usize) -> io::Result<()> {
    let mut buf = [0u8; BUF_SIZE];
    let mut out_buf = [0u8; BUF_SIZE * 4 / 3];

    let mut out = WrapedOutput {
        out: &mut io::stdout(),
        wrap: wrap,
    };

    loop {
        let count = try!(file.read(&mut buf[..]));

        if count == 0 {
            try!(out.write(b"\n"));
            break;
        }

        let encode_count = base64::encode(
            &buf[..count], &mut out_buf
        );

        try!(out.write(&out_buf[..encode_count]));
    }

    Ok(())
}

fn decode(file: &mut io::Read) -> io::Result<()> {
    let mut buf = [0u8; BUF_SIZE];
    let mut out_buf = [0u8; BUF_SIZE * 3 / 4];
    let mut stdout = io::stdout();

    loop {
        let count = try!(file.read(&mut buf[..]));
        if count == 0 {
            break;
        }

        match base64::decode(&buf[..count], &mut out_buf) {
            Ok(count) => {
                stdout.write(&mut out_buf[..count]).unwrap();
            },
            Err(msg) => {
                panic!(msg.as_bytes());
            },
        }
    }

    Ok(())
}

fn process(file: &mut io::Read, is_decode: bool, wrap: usize) {
    if is_decode {
        decode(file).unwrap();
    } else {
        encode(file, wrap).unwrap();
    }
}

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

    if args.flag_version {
        println!("base64 v{}", VERSION);
        return;
    }

    let wrap = match args.flag_wrap {
        Some(count) => count,
        None        => 76,
    };

    if args.arg_file != "" {
        let filename = args.arg_file;

        let path = Path::new(&filename);
        let mut file = match File::open(&path) {
            Err(why) => panic!("couldn't open {}: {}",
                               path.display(), why.description()),
            Ok(file) => file,
        };
        process(&mut file, args.flag_decode, wrap);
    } else {
        process(&mut io::stdin(), args.flag_decode, wrap);
    }
}

#[cfg(test)]
mod tests {
    use super::{WrapedOutput};
    use std::io::{Write};

    fn check_write(wrap: usize, data: &str) {
        let mut file = Vec::new();
        {
            let mut out = WrapedOutput { out: &mut file, wrap: wrap };
            let _ = out.write(data.as_bytes());
        }
        assert_eq!(file, _wrap(wrap, data));
    }

    fn _wrap(wrap: usize, data: &str) -> Vec<u8> {
        let mut res = Vec::new();
        for (i, &chr) in data.as_bytes().iter().enumerate() {
            if wrap != 0 &&
                i != 0 &&
                i % wrap == 0
            {
                res.push('\n' as u8);
            }
            res.push(chr);
        }
        res
    }

    #[test]
    fn test_write_wrapper() {
        let data = [
            "",
            "q",
            "test",
            "\n\n\n\n",
        ];

        for text in data.iter() {
            for i in 0..text.len() {
                check_write(i, text);
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::{env, process};

fn main() {
    let path_or_url = match env::args().nth(1) {
        Some(arg) => arg,
        None => {
            eprintln!("usage: open <path-or-url>");
            process::exit(1);
        }
    };

    match open::that(&path_or_url) {
        Ok(status) if status.success() => (),
        Ok(status) => match status.code() {
            Some(code) => print_error_and_exit(code, &path_or_url, &format!("error code: {}", code)),
            None => print_error_and_exit(3, &path_or_url, "error unknown"),
        },
        Err(err) => print_error_and_exit(3, &path_or_url, &err.to_string()),
    }
}

fn print_error_and_exit(code: i32, path: &str, error_message: &str) -> ! {
    eprintln!(
        "An error occurred when opening '{}': {}",
        path, error_message
    );
    process::exit(code);
}
<commit_msg>cargo fmt<commit_after>use std::{env, process};

fn main() {
    let path_or_url = match env::args().nth(1) {
        Some(arg) => arg,
        None => {
            eprintln!("usage: open <path-or-url>");
            process::exit(1);
        }
    };

    match open::that(&path_or_url) {
        Ok(status) if status.success() => (),
        Ok(status) => match status.code() {
            Some(code) => {
                print_error_and_exit(code, &path_or_url, &format!("error code: {}", code))
            }
            None => print_error_and_exit(3, &path_or_url, "error unknown"),
        },
        Err(err) => print_error_and_exit(3, &path_or_url, &err.to_string()),
    }
}

fn print_error_and_exit(code: i32, path: &str, error_message: &str) -> ! {
    eprintln!(
        "An error occurred when opening '{}': {}",
        path, error_message
    );
    process::exit(code);
}
<|endoftext|>


<commit_before>use std::net::{TcpListener, TcpStream};
use std::io::prelude::*;
use std::io;

fn main() {

    let listener = TcpListener::bind("127.0.0.1:8000").expect("failed to start server");

    #[derive(Debug)]
    enum HTTPMethod {
        POST,
        GET,
        PUT,
        HEAD,
        OPTIONS,
        DELETE,
        NONE,
    }

    #[derive(Debug)]
    struct Request {
        method: HTTPMethod,
        resource: String,
        http_version: String,
        content_length: u64,
        content: String,
    }

    fn read_request(stream: &TcpStream) -> Request {
        let istream = stream.try_clone().expect("couldn't clone");
        let reader = io::BufReader::new(istream);
        let mut request_string = String::new();
        let mut l;

        let mut request = Request {
            method: HTTPMethod::NONE,
            resource: String::new(),
            http_version: String::new(),
            content_length: 0,
            content: String::new(),
        };

        for (i, line) in reader.lines().enumerate() {
            l = line.unwrap();

            if i == 0 {
                let mut iter = l.split_whitespace();
                request.method = match iter.next().unwrap() {
                    "GET" => HTTPMethod::GET,
                    "POST" => HTTPMethod::POST,
                    "PUT" => HTTPMethod::PUT,
                    "HEAD" => HTTPMethod::HEAD,
                    "OPTIONS" => HTTPMethod::OPTIONS,
                    "DELETE" => HTTPMethod::DELETE,
                    &_ => HTTPMethod::NONE,
                };
                request.resource = iter.next().unwrap().to_string();
                request.http_version = iter.next().unwrap().to_string();
            }
            match l.as_str() {
                "" => {
                    break;
                },
                a => {
                    let mut iter = a.split_whitespace();
                    match iter.next().unwrap() {
                        "Content-Length:" => {
                            let cl = iter.next().unwrap();
                            request.content_length = cl.parse().unwrap();
                        },
                        _ => {
                            request_string.push_str(&l);
                            request_string.push_str("\n");
                        },
                    }
                },
            }
        }
        if request.content_length > 0 {
            let mut buf = vec![];
            let content_stream = stream.try_clone().expect("");
            let mut handle = content_stream.take(request.content_length);
            println!("{}", request.content_length);
            handle.read(&mut buf).unwrap();
            println!("Content: {:?}", buf);
        }
        let mut stream = stream;
        stream.flush().expect("stream couldn't be flushed");
        println!("finished reading");
        println!("{:?}", request_string);
        request
    }

    fn handle_client(mut stream: TcpStream) {
        println!("Hello, world!");

        let request;

        request = read_request(&stream);
        println!("{:?}", request);

        stream.write_all(b"HTTP/1.0 200 OK\nContent-Type: text/html\n\nHello there!").expect("write failed");

        stream.flush().expect("stream couldn't be flushed");
    }

    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                handle_client(stream);
            }
            Err(e) => println!("{:?}", e)
        }
    }
}
<commit_msg>1.Handle Content-Length (replace the BufReader.lines() with a loop + BufReader.read_line(), to be able to read following bytes in the stream after a break;) 2.Remove istream<commit_after>use std::net::{TcpListener, TcpStream};
use std::io::prelude::*;
use std::io;

fn main() {

    let listener = TcpListener::bind("127.0.0.1:8000").expect("failed to start server");

    #[derive(Debug)]
    enum HTTPMethod {
        POST,
        GET,
        PUT,
        HEAD,
        OPTIONS,
        DELETE,
        NONE,
        Other(String),
    }

    #[derive(Debug)]
    struct Request {
        method: HTTPMethod,
        resource: String,
        http_version: String,
        content_length: u64,
        content: String,
    }

    fn read_request(stream: &TcpStream) -> Request {
        let mut reader = io::BufReader::new(stream);
        let mut request_string = String::new();
        let mut l: String;

        let mut request = Request {
            method: HTTPMethod::NONE,
            resource: String::new(),
            http_version: String::new(),
            content_length: 0,
            content: String::new(),
        };

        let mut i:i32 = 0;

        loop {
            l = String::new();
            reader.by_ref().read_line(&mut l).unwrap();
            l = l.trim_right().to_string();

            println!("{}", l);

            if i == 0 {
                let mut iter = l.split_whitespace();
                request.method = match iter.next().unwrap() {
                    "GET" => HTTPMethod::GET,
                    "POST" => HTTPMethod::POST,
                    "PUT" => HTTPMethod::PUT,
                    "HEAD" => HTTPMethod::HEAD,
                    "OPTIONS" => HTTPMethod::OPTIONS,
                    "DELETE" => HTTPMethod::DELETE,
                    m => HTTPMethod::Other(m.to_string()),
                };
                request.resource = iter.next().unwrap().to_string();
                request.http_version = iter.next().unwrap().to_string();
            }
            match l.as_str() {
                "" => {
                    println!("breaking now {}", i);
                    break;
                },
                a => {
                    let mut iter = a.split_whitespace();
                    match iter.next().unwrap() {
                        "Content-Length:" => {
                            let cl = iter.next().unwrap();
                            request.content_length = cl.parse().unwrap();
                        },
                        _ => {
                            request_string.push_str(&l);
                            request_string.push_str("\n");
                        },
                    }
                },
            }

            i += 1;
        }

        if request.content_length > 0 {
            let mut buf = String::new();
            let mut handle = reader.by_ref().take(request.content_length);
            println!("{}", request.content_length);
            let read = handle.read_to_string(&mut buf).unwrap();
            println!("Content: {:?}, {}", buf, read);
            request.content = buf;
        }

        let mut stream = stream;
        stream.flush().expect("stream couldn't be flushed");
        println!("finished reading");
        println!("{:?}", request_string);
        request
    }

    fn handle_client(mut stream: TcpStream) {
        println!("Hello, world!");

        let request;

        request = read_request(&stream);
        println!("{:?}", request);

        stream.write_all(b"HTTP/1.0 200 OK\nContent-Type: text/html\n\nHello there!").expect("write failed");

        stream.flush().expect("stream couldn't be flushed");
    }

    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                handle_client(stream);
            }
            Err(e) => println!("{:?}", e)
        }
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>Add the piston tutorials initial code as a base<commit_after>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;

use piston::window::WindowSettings;
use piston::event_loop::*;
use piston::input::*;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{ GlGraphics, OpenGL };

pub struct App {
    gl: GlGraphics, // OpenGL drawing backend.
    rotation: f64   // Rotation for the square.
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        use graphics::*;

        const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 1.0];
        const RED:   [f32; 4] = [1.0, 0.0, 0.0, 1.0];

        let square = rectangle::square(0.0, 0.0, 50.0);
        let rotation = self.rotation;
        let (x, y) = ((args.width / 2) as f64,
                      (args.height / 2) as f64);

        self.gl.draw(args.viewport(), |c, gl| {
            // Clear the screen.
            clear(GREEN, gl);

            let transform = c.transform.trans(x, y)
                                       .rot_rad(rotation)
                                       .trans(-25.0, -25.0);

            // Draw a box rotating around the middle of the screen.
            rectangle(RED, square, transform, gl);
        });
    }

    fn update(&mut self, args: &UpdateArgs) {
        // Rotate 2 radians per second.
        self.rotation += 2.0 * args.dt;
    }
}

fn main() {
    // Change this to OpenGL::V2_1 if not working.
    let opengl = OpenGL::V3_2;

    // Create an Glutin window.
    let mut window: Window = WindowSettings::new(
            "spinning-square",
            [200, 200]
        )
        .opengl(opengl)
        .exit_on_esc(true)
        .build()
        .unwrap();

    // Create a new game and run it.
    let mut app = App {
        gl: GlGraphics::new(opengl),
        rotation: 0.0
    };

    let mut events = Events::new(EventSettings::new());
    while let Some(e) = events.next(&mut window) {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }

        if let Some(u) = e.update_args() {
            app.update(&u);
        }
    }
}
<|endoftext|>


<commit_before>#![feature(question_mark)]
#![feature(associated_consts)]
#![feature(custom_derive, plugin)]

#![plugin(serde_macros)]

extern crate mio;
extern crate slab;
extern crate uuid;
extern crate byteorder;
extern crate serde;
extern crate serde_json;

use mio::tcp::*;
use slab::Slab;

pub use self::packet::*;
pub use self::node::*;

pub mod packet;
pub mod node;
pub mod io;

const SERVER_TOKEN: mio::Token = mio::Token(0);

pub struct Parapet
{
    pub listener: TcpListener,
    pub pending_connections: Slab<Connection, mio::Token>,
    pub nodes: Slab<Node, mio::Token>,
}

impl Parapet
{
    pub fn bind<A>(addr: A) -> Result<Self, std::io::Error>
        where A: std::net::ToSocketAddrs {
        let mut addresses = addr.to_socket_addrs()?;
        let address = addresses.next().expect("could not resolve address");

        let listener = TcpListener::bind(&address)?;
        Ok(Parapet {
            listener: listener,
            pending_connections: Slab::with_capacity(1024),
            nodes: Slab::with_capacity(1024),
        })
    }

    pub fn run(&mut self) -> Result<(), std::io::Error> {
        let poll = mio::Poll::new()?;
        poll.register(&self.listener, SERVER_TOKEN, mio::Ready::readable(),
            mio::PollOpt::edge())?;

        println!("running server");

        // Create storage for events
        let mut events = mio::Events::with_capacity(1024);

        loop {
            poll.poll(&mut events, None).unwrap();

            for event in events.iter() {
                match event.token() {
                    SERVER_TOKEN => {
                        // Accept and drop the socket immediately, this will close
                        // the socket and notify the client of the EOF.
                        let (socket, addr) = self.listener.accept()?;

                        println!("accepted connection from {:?}", addr);

                        let entry = self.pending_connections.vacant_entry().expect("ran out of connections");

                        poll.register(&socket, entry.index(), mio::Ready::readable(),
                            mio::PollOpt::edge())?;

                        entry.insert(Connection {
                            socket: socket,
                            builder: io::Builder::new(),
                        });
                    },
                    token => {
                        assert_eq!(event.kind().is_readable(), true);

                        if let Some(mut pending_connection) = self.pending_connections.entry(token) {
                            pending_connection.get_mut().process_incoming_data()?;

                            if let Some(packet) = pending_connection.get_mut().take_packet()? {
                                match packet {
                                    Packet::Hello(ref hello) => {
                                        let connection = pending_connection.remove();

                                        self.nodes.insert(Node {
                                            connection: Some(connection),
                                            uuid: hello.uuid,
                                        }).ok();
                                    },
                                }
                            }
                        } else if let Some(_node) = self.nodes.get_mut(token) {
                            return Ok(());
                        } else {
                            unreachable!()
                        }
                    },
                }
            }
        }
    }
}

fn main() {
    let mut parapet = Parapet::bind("127.0.0.1:45722").unwrap();
    parapet.run().unwrap();
}

<commit_msg>Support 'Hello' packets to nodes<commit_after>#![feature(question_mark)]
#![feature(associated_consts)]
#![feature(custom_derive, plugin)]

#![plugin(serde_macros)]

extern crate mio;
extern crate slab;
extern crate uuid;
extern crate byteorder;
extern crate serde;
extern crate serde_json;

use mio::tcp::*;
use slab::Slab;

pub use self::packet::*;
pub use self::node::*;

pub mod packet;
pub mod node;
pub mod io;

const SERVER_TOKEN: mio::Token = mio::Token(0);

pub struct Parapet
{
    pub listener: TcpListener,
    pub pending_connections: Slab<Connection, mio::Token>,
    pub nodes: Slab<Node, mio::Token>,
}

impl Parapet
{
    pub fn bind<A>(addr: A) -> Result<Self, std::io::Error>
        where A: std::net::ToSocketAddrs {
        let mut addresses = addr.to_socket_addrs()?;
        let address = addresses.next().expect("could not resolve address");

        let listener = TcpListener::bind(&address)?;
        Ok(Parapet {
            listener: listener,
            pending_connections: Slab::with_capacity(1024),
            nodes: Slab::with_capacity(1024),
        })
    }

    pub fn run(&mut self) -> Result<(), std::io::Error> {
        let poll = mio::Poll::new()?;
        poll.register(&self.listener, SERVER_TOKEN, mio::Ready::readable(),
            mio::PollOpt::edge())?;

        println!("running server");

        // Create storage for events
        let mut events = mio::Events::with_capacity(1024);

        loop {
            poll.poll(&mut events, None).unwrap();

            for event in events.iter() {
                match event.token() {
                    SERVER_TOKEN => {
                        // Accept and drop the socket immediately, this will close
                        // the socket and notify the client of the EOF.
                        let (socket, addr) = self.listener.accept()?;

                        println!("accepted connection from {:?}", addr);

                        let entry = self.pending_connections.vacant_entry().expect("ran out of connections");

                        poll.register(&socket, entry.index(), mio::Ready::readable(),
                            mio::PollOpt::edge())?;

                        entry.insert(Connection {
                            socket: socket,
                            builder: io::Builder::new(),
                        });
                    },
                    token => {
                        assert_eq!(event.kind().is_readable(), true);

                        if let Some(mut pending_connection) = self.pending_connections.entry(token) {
                            pending_connection.get_mut().process_incoming_data()?;

                            if let Some(packet) = pending_connection.get_mut().take_packet()? {
                                match packet {
                                    Packet::Hello(ref hello) => {
                                        let connection = pending_connection.remove();

                                        self.nodes.insert(Node {
                                            connection: Some(connection),
                                            uuid: hello.uuid,
                                        }).ok();
                                    },
                                }
                            }
                        } else if let Some(mut node) = self.nodes.entry(token) {
                            node.get_mut().connection.as_mut().unwrap().process_incoming_data()?;

                            if let Some(packet) = node.get_mut().connection.as_mut().unwrap().take_packet()? {
                                match packet {
                                    // Adding a new node to the network, but not directly connected
                                    // to us.
                                    Packet::Hello(ref hello) => {
                                        self.nodes.insert(Node {
                                            uuid: hello.uuid,
                                            connection: None,
                                        });
                                    },
                                }
                            }
                        } else {
                            unreachable!()
                        }
                    },
                }
            }
        }
    }
}

fn main() {
    let mut parapet = Parapet::bind("127.0.0.1:45722").unwrap();
    parapet.run().unwrap();
}

<|endoftext|>


<commit_before>#![feature(phase)]
extern crate serialize;
#[phase(plugin)] extern crate docopt_macros;
extern crate docopt;
extern crate core;
extern crate collections;

use docopt::FlagParser;
use std::io::BufferedReader;
use std::io::BufferedWriter;
use std::io::File;
use core::result::Result;
use collections::string::String;
use collections::vec::Vec;

// Interleaver takes N files (e.g., i_1.txt ... i_N.txt) and transforms them into N output files
// named o_1.txt ... o_N.txt.  The lines of the input files must be prefixed with time stamps.  The
// output files contain the same content as the input files but only one file is allowed to make
// progress on a given line.  The other files are empty.

docopt!(Args, "
Usage:
  interleaver <file>...

Options:
  -h, --help    Show this screen.
", )

type BrType = BufferedReader<core::result::Result<std::io::fs::File,std::io::IoError>>;
type BwType = BufferedWriter<core::result::Result<std::io::fs::File,std::io::IoError>>;

fn main() {
  let args: Args = FlagParser::parse().unwrap_or_else(|e| e.exit());

  // The Args struct satisfies `Show`:
  println!("{}", args);

  let file_names = args.arg_file;
  let paths_it = file_names.iter ().map (|n| Path::new(n.clone ()));
  let files_it = paths_it.map (|path| File::open(&path));
  let mut buffered_readers_it = files_it.map (|file| BufferedReader::new (file));
  let mut buffered_readers_vec : Vec<BrType> = buffered_readers_it.collect ();

  let paths_out_it = range (0u, file_names.len ()).map (|i| Path::new (i.to_string()));
  let files_out_it = paths_out_it.map (|path_out| File::open(&path_out));
  let mut buffered_writers_it = files_out_it.map (|file_out| BufferedWriter::new (file_out));
  let mut buffered_writers_vec : Vec<BwType> = buffered_writers_it.collect ();

  let mut done;
  let mut i = 0;

  loop {
    done = true;
    for buffered_reader in buffered_readers_vec.mut_iter () {
      let mut lines = buffered_reader.lines ();
      match lines.next () {
        None => (),
        Some (line) => {
          buffered_writers_vec.get_mut (i).write_str (line.unwrap ().as_slice ());
          i = i + 1;
          done = false;
        }
      }
    }
    if done { break; }
  }

  // let line_readers_it = buffered_readers_vec.iter().map (|mut buffered_reader| { buffered_reader.read_to_string(); });

  // let line_iterators = readers.map (|mut reader| reader.lines ());

  // let c = args.arg_FILENAMES.len();

  // let mut candidates : Vec<Option<IoResult<String>>> = Vec::new ();

  // for line_iterator in line_iterators.iter () {
  //   // let line = line_iterator.next ();
  //   // candidates.push (line);
  // }

  // let path = Path::new("p054_poker.txt");

  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //   let l = line.unwrap ();
  // }
}
<commit_msg>A bit more error checking<commit_after>#![feature(phase)]
extern crate serialize;
#[phase(plugin)] extern crate docopt_macros;
extern crate docopt;
extern crate core;
extern crate collections;

use docopt::FlagParser;
use std::io::BufferedReader;
use std::io::BufferedWriter;
use std::io::File;
use core::result::Result;
use collections::string::String;
use collections::vec::Vec;

// Interleaver takes N files (e.g., i_1.txt ... i_N.txt) and transforms them into N output files
// named o_1.txt ... o_N.txt.  The lines of the input files must be prefixed with time stamps.  The
// output files contain the same content as the input files but only one file is allowed to make
// progress on a given line.  The other files are empty.

docopt!(Args, "
Usage:
  interleaver <file>...

Options:
  -h, --help    Show this screen.
", )

type BrType = BufferedReader<core::result::Result<std::io::fs::File,std::io::IoError>>;
type BwType = BufferedWriter<core::result::Result<std::io::fs::File,std::io::IoError>>;

fn main() {
    let args: Args = FlagParser::parse().unwrap_or_else(|e| e.exit());

    println!("Starting {}", args);

    let file_names = args.arg_file;
    let file_count = file_names.len ();
    let paths_it = file_names.iter ().map (|n| Path::new(n.clone ()));
    let files_it = paths_it.map (|path| File::open(&path));
    let mut buffered_readers_it = files_it.map (|file| BufferedReader::new (file));
    let mut buffered_readers_vec : Vec<BrType> = buffered_readers_it.collect ();

    let paths_out_it = range (0u, file_names.len ()).map (|i| Path::new (i.to_string()));
    let files_out_it = paths_out_it.map (|path_out| File::open(&path_out));
        // match res {
        //     Ok(_)  => println!("Successfully opened"),
        //     Err(e) => fail!("Could not open output file");
        // };
    let mut buffered_writers_it = files_out_it.map (|file_out| BufferedWriter::new (file_out) );

    let mut buffered_writers_vec : Vec<BwType> = buffered_writers_it.collect ();

    let mut done;
    let mut i = 0;

    loop {
        done = true;
        for buffered_reader in buffered_readers_vec.mut_iter () {
            let mut lines = buffered_reader.lines ();
            match lines.next () {
                None => (),
                Some (line) => {
                    let target = buffered_writers_vec.get_mut (i);
                    let res = target.write_str (line.unwrap ().as_slice ());
                    match res {
                        Ok(_) => {
                            i = (i + 1) % file_count;
                            done = false;
                        }
                        Err(e) => {
                            let file_name = file_names.get (i);
                            fail! ("Could not write to {}: {}", file_name, e);
                        }
                    }
                }
            }
        }
        if done { break; }
    }

    // let line_readers_it = buffered_readers_vec.iter().map (|mut buffered_reader| { buffered_reader.read_to_string(); });

    // let line_iterators = readers.map (|mut reader| reader.lines ());

    // let c = args.arg_FILENAMES.len();

    // let mut candidates : Vec<Option<IoResult<String>>> = Vec::new ();

    // for line_iterator in line_iterators.iter () {
    //   // let line = line_iterator.next ();
    //   // candidates.push (line);
    // }

    // let path = Path::new("p054_poker.txt");

    // let mut file = BufferedReader::new(File::open(&path));
    // for line in file.lines() {
    //   let l = line.unwrap ();
    // }
}
<|endoftext|>


<commit_before>use clap::Clap;
use std::cmp::Ordering;
use std::fs::File;

fn normalize_col(col: &str) -> String {
    lazy_static::lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"\(.*?\)").unwrap();
    }
    let mut col = RE
        .replace_all(col, "")
        .to_lowercase()
        .trim()
        .replace(" ", "_")
        .replace(".", "_")
        .replace("-", "_")
        .replace("/", "_")
        .replace("?", "")
        .replace(",", "_")
        .replace("&", "_")
        .replace("#", "");
    if !col.chars().next().map(char::is_alphabetic).unwrap_or(true) {
        col = format!("c_{}", col)
    }
    col
}

fn _create_table(db: &mut rusqlite::Connection, table_name: &str, cols: &[String]) {
    let create_columns = cols
        .iter()
        .map(|c| format!("{} varchar", c))
        .collect::<Vec<String>>()
        .join(", ");
    db.execute(
        &format!("CREATE TABLE {} ({})", table_name, create_columns),
        &[] as &[&dyn rusqlite::types::ToSql],
    )
    .unwrap();
}

fn _load_table_from_path(
    db: &mut rusqlite::Connection,
    table_name: &str,
    path: &str,
    delimiter: u8,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
    let mut num_rows = 0;
    let f = File::open(path)?;
    let file_size = f.metadata().unwrap().len();
    let mut reader = csv::ReaderBuilder::new()
        .flexible(true)
        .delimiter(delimiter)
        .from_reader(f);

    let normalized_cols =
        reader
            .headers()?
            .iter()
            .map(normalize_col)
            .fold(vec![], |mut v, orig_col| {
                let mut col = orig_col.clone();
                let mut i = 1;
                while v.contains(&col) {
                    col = format!("{}_{}", orig_col, i);
                    i += 1
                }
                v.push(col);
                v
            });
    _create_table(db, table_name, &normalized_cols);

    let insert_query = format!(
        "INSERT INTO {} VALUES ({})",
        table_name,
        normalized_cols
            .iter()
            .map(|_| "?")
            .collect::<Vec<_>>()
            .join(", ")
    );
    let pb = indicatif::ProgressBar::new(file_size);
    pb.set_style(
        indicatif::ProgressStyle::default_bar()
            .template("[{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})")
            .progress_chars("#>-"),
    );
    let mut records = reader.records();
    let tx = db.transaction().unwrap();
    {
        let mut stmt = tx.prepare(&insert_query).expect("tx.prepare() failed");
        while let Some(row) = records.next() {
            let mut row = row?;
            match row.len().cmp(&normalized_cols.len()) {
                Ordering::Less => {
                    for _ in 0..normalized_cols.len() - row.len() {
                        row.push_field("");
                    }
                }
                Ordering::Greater => {
                    panic!("Too many fields on row {}, fields: {:?}", num_rows + 1, row);
                }
                Ordering::Equal => {}
            }
            stmt.execute(&row).unwrap();

            num_rows += 1;
            if num_rows % 10000 == 0 {
                pb.set_position(records.reader().position().byte())
            }
        }
    }
    tx.commit().unwrap();
    pb.finish();

    println!(
        "Loaded {} rows into {}({})",
        num_rows,
        table_name,
        normalized_cols.join(", "),
    );
    Ok(normalized_cols)
}

struct FromAnySqlType {
    value: String,
}

impl rusqlite::types::FromSql for FromAnySqlType {
    fn column_result(
        value: rusqlite::types::ValueRef<'_>,
    ) -> Result<FromAnySqlType, rusqlite::types::FromSqlError> {
        let result = match value {
            rusqlite::types::ValueRef::Null => "null".to_string(),
            rusqlite::types::ValueRef::Integer(v) => v.to_string(),
            rusqlite::types::ValueRef::Real(v) => v.to_string(),
            rusqlite::types::ValueRef::Blob(v) | rusqlite::types::ValueRef::Text(v) => {
                String::from_utf8(v.to_vec()).unwrap()
            }
        };
        Ok(FromAnySqlType { value: result })
    }
}

fn _prepare_query<'a>(
    conn: &'a mut rusqlite::Connection,
    query: &str,
) -> Result<rusqlite::Statement<'a>, String> {
    conn.prepare(&query).map_err(|e| e.to_string())
}

fn _handle_query(conn: &mut rusqlite::Connection, line: &str) -> Result<(), String> {
    let mut stmt = _prepare_query(conn, line)?;

    let mut table = comfy_table::Table::new();
    table.load_preset("││──╞═╪╡┆    ┬┴┌┐└┘");
    table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);
    let mut title_row = comfy_table::Row::new();
    for col in stmt.column_names() {
        title_row.add_cell(comfy_table::Cell::new(col));
    }
    table.set_header(title_row);

    let mut results = stmt.query(&[] as &[&dyn rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        let mut row = comfy_table::Row::new();
        for i in 0..r.column_count() {
            let cell: FromAnySqlType = r.get(i).unwrap();
            row.add_cell(comfy_table::Cell::new(&cell.value));
        }
        table.add_row(row);
    }
    println!("{}", table);
    Ok(())
}

fn _handle_export(conn: &mut rusqlite::Connection, line: &str) -> Result<(), String> {
    lazy_static::lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"^\.export\(([\w_\-\./]+)\) (.*)").unwrap();
    }
    let caps = RE
        .captures(line)
        .ok_or_else(|| "Must match `.export(file-name) SQL`".to_owned())?;
    let destination_path = &caps[1];
    let query = &caps[2];

    let mut stmt = _prepare_query(conn, query)?;

    let mut writer = csv::Writer::from_path(destination_path).unwrap();
    writer.write_record(stmt.column_names()).unwrap();

    let mut results = stmt.query(&[] as &[&dyn rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        writer
            .write_record((0..r.column_count()).map(|i| {
                let cell: FromAnySqlType = r.get(i).unwrap();
                cell.value
            }))
            .unwrap();
    }

    Ok(())
}

fn _process_query(conn: &mut rusqlite::Connection, line: &str) {
    let result = if line.starts_with(".export") {
        _handle_export(conn, line)
    } else if line.starts_with(".schema") {
        _handle_query(
            conn,
            "SELECT sql AS schema FROM sqlite_master WHERE name like 't%'",
        )
    } else {
        _handle_query(conn, line)
    };
    if let Err(e) = result {
        println!("{}", e);
    }
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [u8; 4] = [b' ', b'(', b')', b','];
impl SimpleWordCompleter {
    fn new(words: Vec<String>) -> SimpleWordCompleter {
        SimpleWordCompleter { words }
    }
}

impl rustyline::Helper for SimpleWordCompleter {}

impl rustyline::hint::Hinter for SimpleWordCompleter {
    type Hint = String;

    fn hint(&self, _line: &str, _pos: usize, _ctx: &rustyline::Context<'_>) -> Option<String> {
        None
    }
}

impl rustyline::highlight::Highlighter for SimpleWordCompleter {}

impl rustyline::validate::Validator for SimpleWordCompleter {}

impl rustyline::completion::Completer for SimpleWordCompleter {
    type Candidate = String;

    fn complete(
        &self,
        line: &str,
        pos: usize,
        _ctx: &rustyline::Context<'_>,
    ) -> rustyline::Result<(usize, Vec<String>)> {
        let (start, word) = rustyline::completion::extract_word(line, pos, None, &BREAK_CHARS);

        let matches = self
            .words
            .iter()
            .filter(|w| w.starts_with(word))
            .cloned()
            .collect();
        Ok((start, matches))
    }
}

#[derive(Clap)]
struct Opts {
    #[clap(long, about = "Use ',' as the delimiter for the CSV")]
    comma: bool,
    #[clap(long, about = "Use '|' as the delimiter for the CSV")]
    pipe: bool,
    #[clap(long, about = "Use '\\t' as the delimiter for the CSV")]
    tab: bool,

    #[clap()]
    paths: Vec<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let opts = Opts::parse();

    let delim = match (opts.comma, opts.pipe, opts.tab) {
        (true, false, false) | (false, false, false) => b',',
        (false, true, false) => b'|',
        (false, false, true) => b'\t',
        _ => {
            eprintln!("Can't pass more than one of --comma, --pipe, and --tab");
            std::process::exit(1);
        }
    };

    let mut conn = rusqlite::Connection::open_in_memory().unwrap();

    let mut base_words = [
        "distinct", "select", "from", "group", "by", "order", "where", "count", "limit", "offset",
        ".export", ".schema",
    ]
    .iter()
    .map(|&s| s.to_string())
    .collect::<Vec<String>>();

    if opts.paths.len() == 1 {
        let mut col_names = _load_table_from_path(&mut conn, "t", &opts.paths[0], delim)?;
        base_words.append(&mut col_names);
    } else {
        for (idx, path) in opts.paths.iter().enumerate() {
            let mut col_names =
                _load_table_from_path(&mut conn, &format!("t{}", idx + 1), path, delim)?;
            base_words.append(&mut col_names);
        }
    }

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_helper(Some(completer));
    loop {
        match rl.readline("> ") {
            Ok(line) => {
                if line.trim().is_empty() {
                    continue;
                }
                _process_query(&mut conn, &line);
                rl.add_history_entry(line);
            }
            Err(rustyline::error::ReadlineError::Interrupted) => {
                println!("Interrupted");
                continue;
            }
            Err(rustyline::error::ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                println!("Error: {}", err);
                break;
            }
        }
    }

    Ok(())
}

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

    #[test]
    fn test_normalize_col() {
        for (value, expected) in &[
            ("", ""),
            ("abc", "abc"),
            ("abc (123)", "abc"),
            ("2/6/2000", "c_2_6_2000"),
            ("COMBO#", "combo"),
        ] {
            assert_eq!(&&normalize_col(value), expected);
        }
    }
}
<commit_msg>Added support for semi-colon delimited files (why!) (#513)<commit_after>use clap::Clap;
use std::cmp::Ordering;
use std::fs::File;

fn normalize_col(col: &str) -> String {
    lazy_static::lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"\(.*?\)").unwrap();
    }
    let mut col = RE
        .replace_all(col, "")
        .to_lowercase()
        .trim()
        .replace(" ", "_")
        .replace(".", "_")
        .replace("-", "_")
        .replace("/", "_")
        .replace("?", "")
        .replace(",", "_")
        .replace("&", "_")
        .replace("#", "");
    if !col.chars().next().map(char::is_alphabetic).unwrap_or(true) {
        col = format!("c_{}", col)
    }
    col
}

fn _create_table(db: &mut rusqlite::Connection, table_name: &str, cols: &[String]) {
    let create_columns = cols
        .iter()
        .map(|c| format!("{} varchar", c))
        .collect::<Vec<String>>()
        .join(", ");
    db.execute(
        &format!("CREATE TABLE {} ({})", table_name, create_columns),
        &[] as &[&dyn rusqlite::types::ToSql],
    )
    .unwrap();
}

fn _load_table_from_path(
    db: &mut rusqlite::Connection,
    table_name: &str,
    path: &str,
    delimiter: u8,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
    let mut num_rows = 0;
    let f = File::open(path)?;
    let file_size = f.metadata().unwrap().len();
    let mut reader = csv::ReaderBuilder::new()
        .flexible(true)
        .delimiter(delimiter)
        .from_reader(f);

    let normalized_cols =
        reader
            .headers()?
            .iter()
            .map(normalize_col)
            .fold(vec![], |mut v, orig_col| {
                let mut col = orig_col.clone();
                let mut i = 1;
                while v.contains(&col) {
                    col = format!("{}_{}", orig_col, i);
                    i += 1
                }
                v.push(col);
                v
            });
    _create_table(db, table_name, &normalized_cols);

    let insert_query = format!(
        "INSERT INTO {} VALUES ({})",
        table_name,
        normalized_cols
            .iter()
            .map(|_| "?")
            .collect::<Vec<_>>()
            .join(", ")
    );
    let pb = indicatif::ProgressBar::new(file_size);
    pb.set_style(
        indicatif::ProgressStyle::default_bar()
            .template("[{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})")
            .progress_chars("#>-"),
    );
    let mut records = reader.records();
    let tx = db.transaction().unwrap();
    {
        let mut stmt = tx.prepare(&insert_query).expect("tx.prepare() failed");
        while let Some(row) = records.next() {
            let mut row = row?;
            match row.len().cmp(&normalized_cols.len()) {
                Ordering::Less => {
                    for _ in 0..normalized_cols.len() - row.len() {
                        row.push_field("");
                    }
                }
                Ordering::Greater => {
                    panic!("Too many fields on row {}, fields: {:?}", num_rows + 1, row);
                }
                Ordering::Equal => {}
            }
            stmt.execute(&row).unwrap();

            num_rows += 1;
            if num_rows % 10000 == 0 {
                pb.set_position(records.reader().position().byte())
            }
        }
    }
    tx.commit().unwrap();
    pb.finish();

    println!(
        "Loaded {} rows into {}({})",
        num_rows,
        table_name,
        normalized_cols.join(", "),
    );
    Ok(normalized_cols)
}

struct FromAnySqlType {
    value: String,
}

impl rusqlite::types::FromSql for FromAnySqlType {
    fn column_result(
        value: rusqlite::types::ValueRef<'_>,
    ) -> Result<FromAnySqlType, rusqlite::types::FromSqlError> {
        let result = match value {
            rusqlite::types::ValueRef::Null => "null".to_string(),
            rusqlite::types::ValueRef::Integer(v) => v.to_string(),
            rusqlite::types::ValueRef::Real(v) => v.to_string(),
            rusqlite::types::ValueRef::Blob(v) | rusqlite::types::ValueRef::Text(v) => {
                String::from_utf8(v.to_vec()).unwrap()
            }
        };
        Ok(FromAnySqlType { value: result })
    }
}

fn _prepare_query<'a>(
    conn: &'a mut rusqlite::Connection,
    query: &str,
) -> Result<rusqlite::Statement<'a>, String> {
    conn.prepare(&query).map_err(|e| e.to_string())
}

fn _handle_query(conn: &mut rusqlite::Connection, line: &str) -> Result<(), String> {
    let mut stmt = _prepare_query(conn, line)?;

    let mut table = comfy_table::Table::new();
    table.load_preset("││──╞═╪╡┆    ┬┴┌┐└┘");
    table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);
    let mut title_row = comfy_table::Row::new();
    for col in stmt.column_names() {
        title_row.add_cell(comfy_table::Cell::new(col));
    }
    table.set_header(title_row);

    let mut results = stmt.query(&[] as &[&dyn rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        let mut row = comfy_table::Row::new();
        for i in 0..r.column_count() {
            let cell: FromAnySqlType = r.get(i).unwrap();
            row.add_cell(comfy_table::Cell::new(&cell.value));
        }
        table.add_row(row);
    }
    println!("{}", table);
    Ok(())
}

fn _handle_export(conn: &mut rusqlite::Connection, line: &str) -> Result<(), String> {
    lazy_static::lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"^\.export\(([\w_\-\./]+)\) (.*)").unwrap();
    }
    let caps = RE
        .captures(line)
        .ok_or_else(|| "Must match `.export(file-name) SQL`".to_owned())?;
    let destination_path = &caps[1];
    let query = &caps[2];

    let mut stmt = _prepare_query(conn, query)?;

    let mut writer = csv::Writer::from_path(destination_path).unwrap();
    writer.write_record(stmt.column_names()).unwrap();

    let mut results = stmt.query(&[] as &[&dyn rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        writer
            .write_record((0..r.column_count()).map(|i| {
                let cell: FromAnySqlType = r.get(i).unwrap();
                cell.value
            }))
            .unwrap();
    }

    Ok(())
}

fn _process_query(conn: &mut rusqlite::Connection, line: &str) {
    let result = if line.starts_with(".export") {
        _handle_export(conn, line)
    } else if line.starts_with(".schema") {
        _handle_query(
            conn,
            "SELECT sql AS schema FROM sqlite_master WHERE name like 't%'",
        )
    } else {
        _handle_query(conn, line)
    };
    if let Err(e) = result {
        println!("{}", e);
    }
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [u8; 4] = [b' ', b'(', b')', b','];
impl SimpleWordCompleter {
    fn new(words: Vec<String>) -> SimpleWordCompleter {
        SimpleWordCompleter { words }
    }
}

impl rustyline::Helper for SimpleWordCompleter {}

impl rustyline::hint::Hinter for SimpleWordCompleter {
    type Hint = String;

    fn hint(&self, _line: &str, _pos: usize, _ctx: &rustyline::Context<'_>) -> Option<String> {
        None
    }
}

impl rustyline::highlight::Highlighter for SimpleWordCompleter {}

impl rustyline::validate::Validator for SimpleWordCompleter {}

impl rustyline::completion::Completer for SimpleWordCompleter {
    type Candidate = String;

    fn complete(
        &self,
        line: &str,
        pos: usize,
        _ctx: &rustyline::Context<'_>,
    ) -> rustyline::Result<(usize, Vec<String>)> {
        let (start, word) = rustyline::completion::extract_word(line, pos, None, &BREAK_CHARS);

        let matches = self
            .words
            .iter()
            .filter(|w| w.starts_with(word))
            .cloned()
            .collect();
        Ok((start, matches))
    }
}

#[derive(Clap)]
struct Opts {
    #[clap(long, about = "Use ',' as the delimiter for the CSV")]
    comma: bool,
    #[clap(long, about = "Use '|' as the delimiter for the CSV")]
    pipe: bool,
    #[clap(long, about = "Use '\\t' as the delimiter for the CSV")]
    tab: bool,
    #[clap(long, about = "Use ';' as the delimiter for the CSV")]
    semicolon: bool,

    #[clap()]
    paths: Vec<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let opts = Opts::parse();

    let delim = match (opts.comma, opts.pipe, opts.tab, opts.semicolon) {
        (true, false, false, false) | (false, false, false, false) => b',',
        (false, true, false, false) => b'|',
        (false, false, true, false) => b'\t',
        (false, false, false, true) => b';',
        _ => {
            eprintln!("Can't pass more than one of --comma, --pipe, and --tab");
            std::process::exit(1);
        }
    };

    let mut conn = rusqlite::Connection::open_in_memory().unwrap();

    let mut base_words = [
        "distinct", "select", "from", "group", "by", "order", "where", "count", "limit", "offset",
        ".export", ".schema",
    ]
    .iter()
    .map(|&s| s.to_string())
    .collect::<Vec<String>>();

    if opts.paths.len() == 1 {
        let mut col_names = _load_table_from_path(&mut conn, "t", &opts.paths[0], delim)?;
        base_words.append(&mut col_names);
    } else {
        for (idx, path) in opts.paths.iter().enumerate() {
            let mut col_names =
                _load_table_from_path(&mut conn, &format!("t{}", idx + 1), path, delim)?;
            base_words.append(&mut col_names);
        }
    }

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_helper(Some(completer));
    loop {
        match rl.readline("> ") {
            Ok(line) => {
                if line.trim().is_empty() {
                    continue;
                }
                _process_query(&mut conn, &line);
                rl.add_history_entry(line);
            }
            Err(rustyline::error::ReadlineError::Interrupted) => {
                println!("Interrupted");
                continue;
            }
            Err(rustyline::error::ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                println!("Error: {}", err);
                break;
            }
        }
    }

    Ok(())
}

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

    #[test]
    fn test_normalize_col() {
        for (value, expected) in &[
            ("", ""),
            ("abc", "abc"),
            ("abc (123)", "abc"),
            ("2/6/2000", "c_2_6_2000"),
            ("COMBO#", "combo"),
        ] {
            assert_eq!(&&normalize_col(value), expected);
        }
    }
}
<|endoftext|>


<commit_before>//  Copyright 2015 Nathanael Merrill

//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at

//    http://www.apache.org/licenses/LICENSE-2.0

//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

extern crate rfmod;

mod playlist;

use std::io;

fn init_fmod() -> Result<rfmod::Sys, rfmod::Result> {
    let fmod = try!(rfmod::Sys::new());

    match fmod.init() {
        rfmod::Result::Ok => Ok(fmod),
        e => Err(e),
    }
}

fn make_channel(rfmod: &rfmod::Sys, song: &str) -> Result<rfmod::Sound, rfmod::Result> {
    rfmod.create_sound(song, None, None)
}

fn main() {
    let rfmod = match init_fmod() {
        Ok(f) => f,
        Err(e) => {
            println!("rfmod init error: {:?}", e);
            return;
        }
    };

    let playlist = playlist::Playlist::new("/home/nathan/Downloads/left.mp3");

    let songa = match make_channel(&rfmod, playlist.get_next_song()) {
        Ok(f) => f,
        Err(e) => {
            println!("Make sound error {:?}", e);
            return;
        }
    };

    let song = match songa.play() {
        Ok(f) => f,
        Err(e) => {
            println!("Chan error {:?}", e);
            return;
        }
    };

    match song.is_playing() {
        Ok(f) => println!("{}", f),
        Err(e) => println!("{:?}", e),
    }

    let stdin = io::stdin();

    let mut input = String::new();
    let mut read;

    loop {
        // Make your choice
        println!("Commands:");
        println!("\tPlay : l");
        println!("\tPause: p");
        println!("\tExit : x");

        input.clear();
        read = stdin.read_line(&mut input);
        if read.is_err() {
            println!("Error: {}", read.unwrap_err());
            return;
        }

        match &*input {
            "l\n" => {
                println!("play");
                song.set_paused(false);
            }
            "p\n" => {
                println!("pause");
                song.set_paused(true);
            }
            "x\n" => {
                println!("exit");
                song.stop();
                break;
            }
            _  => println!("Unknwon command."),
        }
    }
    println!("Goodbye!");
}
<commit_msg>Reorganize user input.<commit_after>//  Copyright 2015 Nathanael Merrill

//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at

//    http://www.apache.org/licenses/LICENSE-2.0

//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

extern crate rfmod;

mod playlist;

use std::io;

enum UIResult {
    Play,
    Pause,
    Exit,
    Error,
    NA,
}

fn init_fmod() -> Result<rfmod::Sys, rfmod::Result> {
    let fmod = try!(rfmod::Sys::new());

    match fmod.init() {
        rfmod::Result::Ok => Ok(fmod),
        e => Err(e),
    }
}

fn manage_ui() -> UIResult {
    let stdin = io::stdin();

    let mut input = String::new();
    let read;

    read = stdin.read_line(&mut input);
    if read.is_err() {
        return UIResult::Error;
    }

    match &*input {
        "l\n" => UIResult::Play,
        "p\n" => UIResult::Pause,
        "x\n" => UIResult::Exit,
        _ => {
            println!("Unknown Command");
            UIResult::NA
        }
    }
}

fn main_loop(rfmod: &rfmod::Sys, playlist: playlist::Playlist) -> rfmod::Result {
    let sound = match rfmod.create_sound(playlist.get_next_song(), None, None) {
        Ok(f) => f,
        Err(e) => {
            println!("Make sound error {:?}", e);
            return e;
        }
    };

    let chan = match sound.play() {
        Ok(f) => f,
        Err(e) => {
            println!("Chan error {:?}", e);
            return e;
        }
    };

    loop {
        match manage_ui() {
            UIResult::Play => {
                println!("play");
                chan.set_paused(false);
            }
            UIResult::Pause => {
                println!("pause");
                chan.set_paused(true);
            }
            UIResult::Exit => {
                println!("exit");
                chan.stop();
                break;
            }
            UIResult::Error => {
                println!("error");
                chan.stop();
                break;
            }
            UIResult::NA => {}
        }
    }

    return rfmod::Result::Ok;
}

fn main() {
    let rfmod = match init_fmod() {
        Ok(f) => f,
        Err(e) => {
            println!("rfmod init error: {:?}", e);
            return;
        }
    };

    let playlist = playlist::Playlist::new("/home/nathan/Downloads/left.mp3");

    println!("Commands:");
    println!("\tPlay : l");
    println!("\tPause: p");
    println!("\tExit : x");

    main_loop(&rfmod, playlist);
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
extern crate rand;
extern crate rustty;
use rustty::{Event, Terminal};
use std::io::Write;
use std::time::Duration;

mod addr;
mod byte;
mod dungeon;
mod geometry;
mod grid;
mod item;
mod monster;
mod player;
mod spell;
mod sprite;
mod tile;
mod timer;
mod util;
mod view;

fn main() {
    let mut terminal = Terminal::new().unwrap();

    let dungeon = dungeon::build().unwrap_or_else(|e| {
        writeln!(std::io::stderr(), "{}", e).unwrap();
        std::process::exit(1)
    });

    let player = player::Player::new(&dungeon);

    loop {
        view::draw_level(&mut terminal, &dungeon[0], &player);
        terminal.swap_buffers().unwrap();
        let event = terminal.get_event(Duration::from_secs(99999)).unwrap().unwrap();
        if event == Event::Key('q') {
            break
        }
    }
}
<commit_msg>don't crash after 1.16 days of inactivity<commit_after>#![allow(dead_code)]
extern crate rand;
extern crate rustty;
use rustty::{Event, Terminal};
use std::io::Write;
use std::time::Duration;

mod addr;
mod byte;
mod dungeon;
mod geometry;
mod grid;
mod item;
mod monster;
mod player;
mod spell;
mod sprite;
mod tile;
mod timer;
mod util;
mod view;

fn main() {
    let mut terminal = Terminal::new().unwrap();

    let dungeon = dungeon::build().unwrap_or_else(|e| {
        writeln!(std::io::stderr(), "{}", e).unwrap();
        std::process::exit(1)
    });

    let player = player::Player::new(&dungeon);

    loop {
        view::draw_level(&mut terminal, &dungeon[0], &player);
        terminal.swap_buffers().unwrap();
        match terminal.get_event(Duration::from_secs(99999)).unwrap() {
            Some(Event::Key('q')) => break,
            _ => {}
        }
    }
}
<|endoftext|>