<commit_before>extern crate ansi_term;
extern crate clap;
extern crate config;
extern crate git2;

mod modules;

use ansi_term::{ANSIString, ANSIStrings};
use clap::{App, Arg};
use config::{Config, File, FileFormat};
use std::path::PathBuf;

fn main() {
    let matches = App::new("contrail")
        .version("0.1.0")
        .about("Fast and configurable shell prompter")
        .arg(Arg::with_name("exit_code")
                 .short("e")
                 .long("exit_code")
                 .value_name("CODE")
                 .help("The exit code of the last-executed command")
                 .takes_value(true))
        .arg(Arg::with_name("config")
                 .short("c")
                 .long("config")
                 .value_name("FILE")
                 .help("The configuration file")
                 .takes_value(true))
        .arg(Arg::with_name("zsh").short("z").long("zsh").help("Enable ZSH mode"))
        .get_matches();

    let mut c = Config::new();

    // Merge in the defaults
    modules::merge_defaults(&mut c);

    // Merge in the config file
    if let Some(f) = matches.value_of("config") {
        c.merge(File::new(f, FileFormat::Toml).required(false))
            .expect("Unable to read the config file!");
    } else if let Some(f) = find_config_file() {
        c.merge(File::new(f.to_str().unwrap(), FileFormat::Toml).required(false))
            .expect("Unable to read the config file!");
    }

    // Merge in the command-line arguments
    if matches.is_present("zsh") {
        c.set("global.shell", "zsh").unwrap();
    }

    // A few things to note:
    // - Calling `c.get()` is a workaround, `c.get_array()` consumes `self`
    // - We do `rev()` because it's easier to handle things like finding
    //   the next module's background color when you go in backwards order
    let module_names: Vec<String> = c.get("global.modules")
        .unwrap()
        .into_array()
        .unwrap_or_default()
        .into_iter()
        .map(|m| m.into_str().unwrap())
        .rev()
        .collect();

    let mut ansi_strings: Vec<ANSIString<'static>> = Vec::new();

    // The name of the last successfully formatted module
    let mut last_successful_format: Option<&str> = None;

    for name in &module_names {
        let formatted_module: Option<ANSIString<'static>>;

        let result = match name.as_ref() {
            "directory" => modules::format_module_directory(&mut c, last_successful_format),
            "exit_code" => {
                let exit_code = matches.value_of("exit_code").unwrap_or("255");
                modules::format_module_exit_code(&mut c, last_successful_format, exit_code)
            }
            "git" => modules::format_module_git(&mut c, last_successful_format),
            "prompt" => {
                let exit_code = matches.value_of("exit_code").unwrap_or("255");
                modules::format_module_prompt(&mut c, last_successful_format, exit_code)
            }
            _ => {
                // The output will be found in the config file
                modules::format_module(&mut c, name, None, last_successful_format)
            }
        };

        // Updates the last formatted module variable and prints it
        // out only if it was successful
        formatted_module = result.1;
        if result.0.is_some() {
            last_successful_format = result.0;
            ansi_strings.insert(0, formatted_module.unwrap());
        }

    }

    print!("{}", ANSIStrings(ansi_strings.as_slice()));
}

/// Looks through typical directories for a `contrail/config.toml`
// TODO Implement and test this
fn find_config_file() -> Option<PathBuf> {
    // This is NOT the desired behavior, this is just for testing
    let pb = PathBuf::from("config.toml");

    if pb.exists() { Some(pb) } else { None }
}
<commit_msg>refactor: automatically detect program version number<commit_after>extern crate ansi_term;
extern crate clap;
extern crate config;
extern crate git2;

mod modules;

use ansi_term::{ANSIString, ANSIStrings};
use clap::{App, Arg};
use config::{Config, File, FileFormat};
use std::path::PathBuf;

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

fn main() {
    let matches = App::new("contrail")
        .version(VERSION)
        .about("Fast and configurable shell prompter")
        .arg(Arg::with_name("exit_code")
                 .short("e")
                 .long("exit_code")
                 .value_name("CODE")
                 .help("The exit code of the last-executed command")
                 .takes_value(true))
        .arg(Arg::with_name("config")
                 .short("c")
                 .long("config")
                 .value_name("FILE")
                 .help("The configuration file")
                 .takes_value(true))
        .arg(Arg::with_name("zsh").short("z").long("zsh").help("Enables ZSH mode"))
        .get_matches();

    let mut c = Config::new();

    // Merge in the defaults
    modules::merge_defaults(&mut c);

    // Merge in the config file
    if let Some(f) = matches.value_of("config") {
        c.merge(File::new(f, FileFormat::Toml).required(false))
            .expect("Unable to read the config file!");
    } else if let Some(f) = find_config_file() {
        c.merge(File::new(f.to_str().unwrap(), FileFormat::Toml).required(false))
            .expect("Unable to read the config file!");
    }

    // Merge in the command-line arguments
    if matches.is_present("zsh") {
        c.set("global.shell", "zsh").unwrap();
    }

    // A few things to note:
    // - Calling `c.get()` is a workaround, `c.get_array()` consumes `self`
    // - We do `rev()` because it's easier to handle things like finding
    //   the next module's background color when you go in backwards order
    let module_names: Vec<String> = c.get("global.modules")
        .unwrap()
        .into_array()
        .unwrap_or_default()
        .into_iter()
        .map(|m| m.into_str().unwrap())
        .rev()
        .collect();

    let mut ansi_strings: Vec<ANSIString<'static>> = Vec::new();

    // The name of the last successfully formatted module
    let mut last_successful_format: Option<&str> = None;

    for name in &module_names {
        let formatted_module: Option<ANSIString<'static>>;

        let result = match name.as_ref() {
            "directory" => modules::format_module_directory(&mut c, last_successful_format),
            "exit_code" => {
                let exit_code = matches.value_of("exit_code").unwrap_or("255");
                modules::format_module_exit_code(&mut c, last_successful_format, exit_code)
            }
            "git" => modules::format_module_git(&mut c, last_successful_format),
            "prompt" => {
                let exit_code = matches.value_of("exit_code").unwrap_or("255");
                modules::format_module_prompt(&mut c, last_successful_format, exit_code)
            }
            _ => {
                // The output will be found in the config file
                modules::format_module(&mut c, name, None, last_successful_format)
            }
        };

        // Updates the last formatted module variable and prints it
        // out only if it was successful
        formatted_module = result.1;
        if result.0.is_some() {
            last_successful_format = result.0;
            ansi_strings.insert(0, formatted_module.unwrap());
        }

    }

    print!("{}", ANSIStrings(ansi_strings.as_slice()));
}

/// Looks through typical directories for a `contrail/config.toml`
// TODO Implement and test this
fn find_config_file() -> Option<PathBuf> {
    // This is NOT the desired behavior, this is just for testing
    let pb = PathBuf::from("config.toml");

    if pb.exists() { Some(pb) } else { None }
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate sdl2_ttf;
extern crate sdl2_engine_helpers;
extern crate uorustlibs;

mod engine;
mod scene;
mod title_scene;
mod skills_scene;
mod text_renderer;

use std::path::Path;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::render::Renderer;
use sdl2_engine_helpers::game_loop::GameLoop;

pub fn make_scene(scene: scene::SceneName, text_renderer: &text_renderer::TextRenderer, renderer: &mut Renderer) -> scene::BoxedScene<scene::SceneName> {
    match scene {
        scene::SceneName::TitleScene => {
            title_scene::TitleScene::new(text_renderer, renderer)
        },
        scene::SceneName::SkillsScene => {
            skills_scene::SkillsScene::new(text_renderer, renderer)
        },
    }
}

pub fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();
    let ttf_subsystem = sdl2_ttf::init().unwrap();

    let window = video_subsystem.window("UO Data Viewer", 1024, 768)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    let mut renderer = window.renderer().build().unwrap();
    let font_path = Path::new("./assets/Bretan.otf");
    let font = ttf_subsystem.load_font(font_path, 16).unwrap();
    let text_renderer = text_renderer::TextRenderer::new(font);

    let mut event_pump = sdl_context.event_pump().unwrap();
    let mut engine = engine::Engine::new(30, event_pump, title_scene::TitleScene::new(&text_renderer, &mut renderer));

    /*game_loop.run(|frame| {
        let mut ended = false;
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit {..}  => {
                    ended = true
                },
                _ => {
                    let scene_event = scene_stack.handle_event(&event);
                    match scene_event {
                        Some(scene::SceneChangeEvent::PopScene) => {
                            scene_stack.pop();
                        },
                        Some(scene::SceneChangeEvent::PushScene(scene)) => {
                            scene_stack.push(make_scene(scene, &text_renderer, &mut renderer))
                        },
                        Some(scene::SceneChangeEvent::SwapScene(scene)) => {
                            scene_stack.pop();
                            scene_stack.push(make_scene(scene, &text_renderer, &mut renderer))
                        },
                        _ => ()
                    }
                }
            }
        }
        scene_stack.render(&mut renderer);
        ended || scene_stack.is_empty()
    });*/
}
<commit_msg>More base engine work<commit_after>extern crate sdl2;
extern crate sdl2_ttf;
extern crate sdl2_engine_helpers;
extern crate uorustlibs;

mod engine;
mod scene;
mod title_scene;
mod skills_scene;
mod text_renderer;

use std::path::Path;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::render::Renderer;
use sdl2_engine_helpers::game_loop::GameLoop;

pub fn make_scene(scene: scene::SceneName, text_renderer: &text_renderer::TextRenderer, renderer: &mut Renderer) -> scene::BoxedScene<scene::SceneName> {
    match scene {
        scene::SceneName::TitleScene => {
            title_scene::TitleScene::new(text_renderer, renderer)
        },
        scene::SceneName::SkillsScene => {
            skills_scene::SkillsScene::new(text_renderer, renderer)
        },
    }
}

pub fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();
    let ttf_subsystem = sdl2_ttf::init().unwrap();

    let window = video_subsystem.window("UO Data Viewer", 1024, 768)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    let mut renderer = window.renderer().build().unwrap();
    let font_path = Path::new("./assets/Bretan.otf");
    let font = ttf_subsystem.load_font(font_path, 16).unwrap();
    let text_renderer = text_renderer::TextRenderer::new(font);

    let mut event_pump = sdl_context.event_pump().unwrap();
    let mut engine = engine::Engine::new(30, event_pump, title_scene::TitleScene::new(&text_renderer, &mut renderer));

    engine.run(|scene, renderer| {
    }, &mut renderer);

    /*game_loop.run(|frame| {
        let mut ended = false;
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit {..}  => {
                    ended = true
                },
                _ => {
                    let scene_event = scene_stack.handle_event(&event);
                    match scene_event {
                        Some(scene::SceneChangeEvent::PopScene) => {
                            scene_stack.pop();
                        },
                        Some(scene::SceneChangeEvent::PushScene(scene)) => {
                            scene_stack.push(make_scene(scene, &text_renderer, &mut renderer))
                        },
                        Some(scene::SceneChangeEvent::SwapScene(scene)) => {
                            scene_stack.pop();
                            scene_stack.push(make_scene(scene, &text_renderer, &mut renderer))
                        },
                        _ => ()
                    }
                }
            }
        }
        scene_stack.render(&mut renderer);
        ended || scene_stack.is_empty()
    });*/
}
<|endoftext|>


<commit_before>
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Token {
    Error,
    Spaces(usize, usize),
    Comment(usize, usize),
}

#[test]
fn test_trivial(){
    assert_eq!(scan(" "), vec![Token::Spaces(0,1)]);
    assert_eq!(scan(" \n\t"), vec![Token::Spaces(0,3)]);
    // assert_eq!(scan("//x"), vec![Token::Comment(0,3)]);
    // assert_eq!(scan("// one"), vec![Token::Comment(0,6)]);
}

struct ScannerState {
    i : usize,
    j : usize,
    token : Token,
}

fn scan(source : & str) -> Vec<Token> {
    let mut state = ScannerState{ i:0, j:0, token : Token::Error };
    scan_spaces(source, &mut state);
    // scan_comment(source, &mut state);
    vec![state.token]
}

fn scan_spaces(source : &str, state : &mut ScannerState){
    let mut l = state.i;
    loop {
        match source.chars().nth(l) {
            Some(' ') | Some('\t') | Some('\n') => l += 1,
            _ => break,
        }
    }
    if state.j < l {
        state.j = l;
        state.token = Token::Spaces(state.i, l)
    }
}

// fn scan_comment(source : &str, state : &mut ScannerState){
    // let mut l = state.i;

// }

fn main() {
    println!("{:?}", scan(" \n\t"));
}

<commit_msg>scan mono-line comments<commit_after>
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Token {
    Error,
    Spaces(usize, usize),
    Comment(usize, usize),
}

#[test]
fn test_trivial(){
    assert_eq!(scan(" "), vec![Token::Spaces(0,1)]);
    assert_eq!(scan(" \n\t"), vec![Token::Spaces(0,3)]);
    assert_eq!(scan("//x"), vec![Token::Comment(0,3)]);
    assert_eq!(scan("// one"), vec![Token::Comment(0,6)]);
}

#[test]
fn test_double(){
    assert_eq!(scan("//xy z\n  "), vec![
        Token::Comment(0,6),
        Token::Spaces(6,9),
    ]);
    assert_eq!(scan("\n  //xy z"), vec![
        Token::Spaces(0,3),
        Token::Comment(3,9),
    ]);
}

struct ScannerState {
    i : usize,
    j : usize,
    token : Token,
}

fn scan(source : & str) -> Vec<Token> {
    let mut state = ScannerState{ i:0, j:0, token : Token::Error };
    let mut res = vec![];
    loop {
        scan_spaces(source, &mut state);
        scan_comment_monoline(source, &mut state);
        if state.token == Token::Error {
            return res
        }
        res.push(state.token);
        state.i = state.j;
        state.token = Token::Error;
    }
}

fn scan_spaces(source : &str, state : &mut ScannerState){
    let mut x = state.i;
    loop {
        match source.chars().nth(x) {
            Some(' ') | Some('\t') | Some('\n') => x += 1,
            _ => break,
        }
    }
    if state.j < x {
        state.j = x;
        state.token = Token::Spaces(state.i, x)
    }
}

fn scan_comment_monoline(source : &str, state : &mut ScannerState){
    let mut x = state.i;
    if source.chars().nth(x) == Some('/') &&
       source.chars().nth(x+1) == Some('/') {
        x += 2;
        loop {
            match source.chars().nth(x) {
                None => break,
                Some('\n') => break,
                Some(_) => x += 1,
            }
        }
    }
    if state.j < x {
        state.j = x;
        state.token = Token::Comment(state.i, x)
    }
}

fn main() {
    println!("{:?}", scan("//xy z\n//a "));
}

<|endoftext|>


<commit_before>extern crate clap;
extern crate unlimited;

//
use std::sync::mpsc::channel;
use std::thread;

use clap::{App, Arg};

use unlimited::core;
use unlimited::core::config::Config;

use unlimited::ui;

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

fn main() {
    let config = parse_command_line();

    let (ui_tx, ui_rx) = channel();
    let (core_tx, core_rx) = channel();

    let ui_name = config.ui_frontend.clone();

    let core_th = { Some(thread::spawn(move || core::start(config, core_rx, ui_tx))) };

    ui::main_loop(ui_name.as_ref(), ui_rx, core_tx);

    if let Some(core_handle) = core_th {
        core_handle.join().unwrap()
    }
}

fn parse_command_line() -> Config {
    let matches = App::new("unlimited")
        .version(VERSION)
        .author("Carl-Erwin Griffith <carl.erwin@gmail.com>")
        .about("unlimited is an experimental editor")
        .args_from_usage("--ui, --ui=[termion|ncurses] 'select user interface fronted'")
        .arg(
            Arg::with_name("FILES")
                .help("list of the files to open")
                .required(false)
                .multiple(true),
        )
        .get_matches();

    let mut ui_frontend = String::new();
    if matches.is_present("ui") {
        let v: Vec<&str> = matches.values_of("ui").unwrap().collect();
        ui_frontend = v[0].to_owned();
    }

    let mut files_list = Vec::new();
    if matches.is_present("FILES") {
        let strs: Vec<&str> = matches.values_of("FILES").unwrap().collect();
        files_list = strs.into_iter().map(|x| x.to_owned()).collect()
    }

    Config {
        files_list,
        ui_frontend,
    }
}
<commit_msg>typo fix<commit_after>extern crate clap;
extern crate unlimited;

//
use std::sync::mpsc::channel;
use std::thread;

use clap::{App, Arg};

use unlimited::core;
use unlimited::core::config::Config;

use unlimited::ui;

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

fn main() {
    let config = parse_command_line();

    let (ui_tx, ui_rx) = channel();
    let (core_tx, core_rx) = channel();

    let ui_name = config.ui_frontend.clone();

    let core_th = { Some(thread::spawn(move || core::start(config, core_rx, ui_tx))) };

    ui::main_loop(ui_name.as_ref(), ui_rx, core_tx);

    if let Some(core_handle) = core_th {
        core_handle.join().unwrap()
    }
}

fn parse_command_line() -> Config {
    let matches = App::new("unlimited")
        .version(VERSION)
        .author("Carl-Erwin Griffith <carl.erwin@gmail.com>")
        .about("unlimited is an experimental editor")
        .args_from_usage("--ui, --ui=[termion|ncurses] 'select user interface frontend'")
        .arg(
            Arg::with_name("FILES")
                .help("list of the files to open")
                .required(false)
                .multiple(true),
        )
        .get_matches();

    let mut ui_frontend = String::new();
    if matches.is_present("ui") {
        let v: Vec<&str> = matches.values_of("ui").unwrap().collect();
        ui_frontend = v[0].to_owned();
    }

    let mut files_list = Vec::new();
    if matches.is_present("FILES") {
        let strs: Vec<&str> = matches.values_of("FILES").unwrap().collect();
        files_list = strs.into_iter().map(|x| x.to_owned()).collect()
    }

    Config {
        files_list,
        ui_frontend,
    }
}
<|endoftext|>


<commit_before>extern crate gtk;
extern crate gtk_sys;
extern crate gdk;
extern crate glib;
extern crate cairo;

use gtk::prelude::*;
use gdk::prelude::*;
use glib::translate::*;

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }

    let window = gtk::Window::new(gtk::WindowType::Toplevel);
    window.set_title("Dropzone");
    window.set_default_size(350, 70);
    window.set_keep_above(true);
    window.set_skip_taskbar_hint(true);
    window.set_skip_pager_hint(true);
    window.set_deletable(false);
    window.set_decorated(false);
    window.set_app_paintable(true);

    window.connect_draw(|window, _context| {
        let cr = cairo::Context::create_from_window(&window.get_window().unwrap());
        cr.set_source_rgba(0.0, 0.0, 0.0, 0.5);
        cr.set_operator(cairo::Operator::Source);
        cr.paint();
        Inhibit(false)
    });
    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(false)
    });
    let update_visual = |window: &gtk::Window, _old_screen: &Option<gdk::Screen>| {
        let screen = gtk::WindowExt::get_screen(window).unwrap();
        let visual = screen.get_rgba_visual();

        window.set_visual(visual.as_ref());
    };
    update_visual(&window, &None);
    window.connect_screen_changed(update_visual);

    let zone = gtk::Label::new(Some("zone"));
    unsafe {
        // FIXME: use wrapped API
        gtk_sys::gtk_drag_dest_set(zone.to_glib_none().0,
                                   gtk_sys::GtkDestDefaults::all(),
                                   std::ptr::null_mut(),
                                   0,
                                   gdk::DragAction::all());
    }
    zone.drag_dest_add_text_targets();
    zone.connect_drag_data_received(|_self, _drag_context, _x, _y, data, _info, _time| {
        if let Some(text) = data.get_text() {
            println!("{}", text);
        }
    });
    window.add(&zone);

    window.show_all();

    gtk::main();
}
<commit_msg>rounded window<commit_after>extern crate gtk;
extern crate gtk_sys;
extern crate gdk;
extern crate glib;
extern crate cairo;

use gtk::prelude::*;
use gdk::prelude::*;
use glib::translate::*;

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }

    let window = gtk::Window::new(gtk::WindowType::Toplevel);
    window.set_title("Dropzone");
    window.set_default_size(64, 64);
    window.set_keep_above(true);
    window.set_skip_taskbar_hint(true);
    window.set_skip_pager_hint(true);
    window.set_deletable(false);
    window.set_decorated(false);
    window.set_app_paintable(true);

    window.connect_draw(|window, _context| {
        let cr = cairo::Context::create_from_window(&window.get_window().unwrap());
        // set window to transparent
        cr.set_source_rgba(0.0, 0.0, 0.0, 0.0);
        cr.set_operator(cairo::Operator::Source);
        cr.paint();

        // draw a circle
        cr.set_source_rgba(0.0, 0.0, 0.0, 0.5);
        cr.arc(32.0, 32.0, 32.0, 0.0, 2.0 * std::f64::consts::PI);
        cr.fill();
        Inhibit(false)
    });
    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(false)
    });
    let update_visual = |window: &gtk::Window, _old_screen: &Option<gdk::Screen>| {
        let screen = gtk::WindowExt::get_screen(window).unwrap();
        let visual = screen.get_rgba_visual();

        window.set_visual(visual.as_ref());
    };
    update_visual(&window, &None);
    window.connect_screen_changed(update_visual);

    let zone = gtk::Label::new(Some("zone"));
    unsafe {
        // FIXME: use wrapped API
        gtk_sys::gtk_drag_dest_set(zone.to_glib_none().0,
                                   gtk_sys::GtkDestDefaults::all(),
                                   std::ptr::null_mut(),
                                   0,
                                   gdk::DragAction::all());
    }
    zone.drag_dest_add_text_targets();
    zone.connect_drag_data_received(|_self, _drag_context, _x, _y, data, _info, _time| {
        if let Some(text) = data.get_text() {
            println!("{}", text);
        }
    });
    window.add(&zone);

    window.show_all();

    gtk::main();
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;
use std::net::TcpStream;
use std::fs::File;

extern crate chrono;
use chrono::*;

extern crate stats;

extern crate clap;
use clap::{Arg, App, ArgMatches};

mod http_status;
mod log_parser;
mod request_response_matcher;
mod filter;
mod analyzer;
mod render;

// http://stackoverflow.com/a/27590832/376138
macro_rules! println_stderr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

fn parse_args<'a>() -> ArgMatches<'a> {
    App::new("Request.log Analyzer")
        .arg(Arg::with_name("filename")
            .index(1)
            .value_name("FILE")
            .required(false)
            .help("Log file to analyze, defaults to stdin")
            .takes_value(true))
        .arg(Arg::with_name("time_filter_minutes")
            .value_name("MINUTES")
            .short("t")
            .help("Limit to the last n minutes")
            .takes_value(true))
        .arg(Arg::with_name("include_term")
            .value_name("TERM")
            .long("include")
            .help("Only includes lines that contain this term")
            .takes_value(true))
        .arg(Arg::with_name("exclude_term")
            .value_name("TERM")
            .long("exclude")
            .help("Excludes lines that contain this term")
            .takes_value(true))
        .arg(Arg::with_name("graphite-server")
            .value_name("GRAPHITE_SERVER")
            .long("graphite-server")
            .help("Send values to this Graphite server instead of stdout")
            .takes_value(true))
        .arg(Arg::with_name("graphite-port")
            .value_name("GRAPHITE_PORT")
            .long("graphite-port")
            .takes_value(true)
            .default_value("2003"))
        .arg(Arg::with_name("graphite-prefix")
            .value_name("GRAPHITE_PREFIX")
            .long("graphite-prefix")
            .help("Prefix for Graphite key, e.g. 'servers.prod.publisher1'")
            .takes_value(true))
        .get_matches()
}

fn main() {
    let args = parse_args();

    let filename = args.value_of("filename").unwrap_or("-");

    let time_filter = match args.value_of("time_filter_minutes") {
        Some(minutes) => Some(Duration::minutes(minutes.parse().unwrap())),
        None => None
    };

    let mut input: Box<io::Read> = match filename {
        "-" => Box::new(io::stdin()),
        _ => Box::new(File::open(filename).unwrap())
    };

    let (requests, responses) = log_parser::parse(&mut input);

    let pairs = request_response_matcher::pair_requests_responses(requests, responses);

    let conditions = filter::FilterConditions {
        include_terms: match args.value_of("include_term") {
            Some(value) => Some(vec![value.to_string()]),
            None => None
        },
        exclude_terms: match args.value_of("exclude_term") {
            Some(value) => Some(vec![value.to_string()]),
            None => None
        },
        latest_time: time_filter,
    };

    let filtered_pairs = filter::filter(pairs, conditions);

    let result = analyzer::analyze(&filtered_pairs);

    match result {
        Some(result) => {
            if args.is_present("graphite-server") {
                let stream = TcpStream::connect(
                    (
                        args.value_of("graphite-server").unwrap(),
                        args.value_of("graphite-port").unwrap().parse().unwrap()
                    )
                ).expect("Could not connect to the Graphite server");

                let timezone = filtered_pairs[0].request.time.timezone();

                render::render_graphite(result, UTC::now().with_timezone(&timezone), args.value_of("graphite-prefix"), stream);
            } else {
                render::render_terminal(result);
            }
        },
        None => println_stderr!("No matching log lines in file.")
    }
}
<commit_msg>Working loop experiment<commit_after>use std::io;
use std::io::prelude::*;
use std::net::TcpStream;
use std::fs::File;

extern crate chrono;
use chrono::*;

extern crate stats;

extern crate clap;
use clap::{Arg, App, ArgMatches};

mod http_status;
mod log_parser;
use log_parser::log_events::*;
mod request_response_matcher;
use request_response_matcher::RequestResponsePair;
mod filter;
mod analyzer;
mod render;

// http://stackoverflow.com/a/27590832/376138
macro_rules! println_stderr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

fn parse_args<'a>() -> ArgMatches<'a> {
    App::new("Request.log Analyzer")
        .arg(Arg::with_name("filename")
            .index(1)
            .value_name("FILE")
            .required(false)
            .help("Log file to analyze, defaults to stdin")
            .takes_value(true))
        .arg(Arg::with_name("time_filter_minutes")
            .value_name("MINUTES")
            .short("t")
            .help("Limit to the last n minutes")
            .takes_value(true))
        .arg(Arg::with_name("include_term")
            .value_name("TERM")
            .long("include")
            .help("Only includes lines that contain this term")
            .takes_value(true))
        .arg(Arg::with_name("exclude_term")
            .value_name("TERM")
            .long("exclude")
            .help("Excludes lines that contain this term")
            .takes_value(true))
        .arg(Arg::with_name("graphite-server")
            .value_name("GRAPHITE_SERVER")
            .long("graphite-server")
            .help("Send values to this Graphite server instead of stdout")
            .takes_value(true))
        .arg(Arg::with_name("graphite-port")
            .value_name("GRAPHITE_PORT")
            .long("graphite-port")
            .takes_value(true)
            .default_value("2003"))
        .arg(Arg::with_name("graphite-prefix")
            .value_name("GRAPHITE_PREFIX")
            .long("graphite-prefix")
            .help("Prefix for Graphite key, e.g. 'servers.prod.publisher1'")
            .takes_value(true))
        .get_matches()
}

fn main() {
    let args = parse_args();

    let filename = args.value_of("filename").unwrap_or("-");

    let time_filter = match args.value_of("time_filter_minutes") {
        Some(minutes) => Some(Duration::minutes(minutes.parse().unwrap())),
        None => None
    };

    let mut input: Box<io::Read> = match filename {
        "-" => Box::new(io::stdin()),
        _ => Box::new(File::open(filename).unwrap())
    };

    let reader = io::BufReader::new(input);

    let lines = reader.lines();

    let mut requests: Vec<Request> = Vec::new();
    let mut responses: Vec<Response> = Vec::new();
    let mut pairs: Vec<RequestResponsePair> = Vec::new();

    for line in lines {
        let line_value = &line.unwrap();

        if line_value.contains("->") {
            match Request::new_from_log_line(&line_value) {
                Ok(r) => {
                    // if time_filter.is_none() ||
                    //   (time_filter.is_some() && r.is_between_times(UTC::now().with_timezone(&r.time.timezone()) - time_filter.unwrap(), UTC::now().with_timezone(&r.time.timezone()))) {
                        requests.push(r);
                    // }
                },
                Err(err) => println_stderr!("Skipped a line: {}", err)
            }
        }

        if line_value.contains("<-") {
            match Response::new_from_log_line(&line_value) {
                Ok(r) => responses.push(r),
                Err(err) => println_stderr!("Skipped a line: {}", err)
            }
        }

        // for ref request in &requests {
        if requests.len() == 0 {
            continue;
        }
        for request_index in 0..(requests.len() - 1) {
            let matching_response_index: Option<usize> = responses.iter().position(|response| requests[request_index].id == response.id );

            if matching_response_index.is_some() {
                let request = requests.remove(request_index);
                let response = responses.remove(matching_response_index.unwrap());

                let pair = RequestResponsePair {
                    request: request,
                    response: response
                };
                // println!("request {:?} has response {:?}", request, response);
                // println!("Requests len {:?}", requests.len());
                // println!("========================================", );
                println!("{:?}", pair);
            }
        }
    }

    // let (requests, responses) = log_parser::parse(&mut input);
    //
    // let pairs = request_response_matcher::pair_requests_responses(requests, responses);
    //
    // let conditions = filter::FilterConditions {
    //     include_terms: match args.value_of("include_term") {
    //         Some(value) => Some(vec![value.to_string()]),
    //         None => None
    //     },
    //     exclude_terms: match args.value_of("exclude_term") {
    //         Some(value) => Some(vec![value.to_string()]),
    //         None => None
    //     },
    //     latest_time: time_filter,
    // };
    //
    // let filtered_pairs = filter::filter(pairs, conditions);
    //
    // let result = analyzer::analyze(&filtered_pairs);
    //
    // match result {
    //     Some(result) => {
    //         if args.is_present("graphite-server") {
    //             let stream = TcpStream::connect(
    //                 (
    //                     args.value_of("graphite-server").unwrap(),
    //                     args.value_of("graphite-port").unwrap().parse().unwrap()
    //                 )
    //             ).expect("Could not connect to the Graphite server");
    //
    //             let timezone = filtered_pairs[0].request.time.timezone();
    //
    //             render::render_graphite(result, UTC::now().with_timezone(&timezone), args.value_of("graphite-prefix"), stream);
    //         } else {
    //             render::render_terminal(result);
    //         }
    //     },
    //     None => println_stderr!("No matching log lines in file.")
    // }
}
<|endoftext|>


<commit_before>//! Uniform point distribution in an annulus using Bridson’s algorithm for
//! Poisson-disc sampling.
//!
//! Bridson, Robert. "Fast Poisson disk sampling in arbitrary dimensions." ACM
//! SIGGRAPH. Vol. 2007. 2007.
//!
//! See also [Visualizing Algorithms](http://bost.ocks.org/mike/algorithms/).
//!
//! Uses [qhull](http://qhull.org/) to generate a Delaunay triangulation.
extern crate docopt;
extern crate rand;
extern crate rustc_serialize;
extern crate gnuplot;
extern crate mersenne_twister;

mod annulus_distribution;

use std::f64::consts::PI;
#[allow(unused_imports)]
use gnuplot::{Figure, Caption, Color, Fix, AxesCommon, PlotOption, DashType, Coordinate, TextColor};
use rand::{Rng, SeedableRng};
use std::io::{Read, Write, Cursor, BufRead};
use std::process::{Command, Stdio};
use docopt::Docopt;
use mersenne_twister::MT19937_64;
use std::ops::Add;
use annulus_distribution::AnnulusDist;

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

static USAGE: &'static str = r"
Simple annulus triangulation generator.

Usage: annulus_mesh [options]
       annulus_mesh (-h | --help | --version)

Options:
    -r INNER        Inner radius [default: 0.2]
    -d DIST         Point distance [default: 0.2]
    -h, --help      Print help
    --plot FILE     Output mesh plot
    --no-show       Do not plot anything
    --version       Print version
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_d: f64,
    flag_r: f64,
    flag_no_show: bool,
    flag_plot: Option<String>,
}

#[derive(Copy, Clone, Debug)]
pub struct Point(f64, f64);

impl Add for Point {
    type Output = Self;

    fn add(self, rhs: Self) -> Self {
        Point(self.0 + rhs.0, self.1 + rhs.1)
    }
}

fn dist_sq(x: Point, y: Point) -> f64 {
    (x.0 - y.0).powi(2) + (x.1 - y.1).powi(2)
}

fn dist(x: Point, y: Point) -> f64 {
    ((x.0 - y.0).powi(2) + (x.1 - y.1).powi(2)).sqrt()
}

fn qhull_triangulation(ps: &[Point]) -> Vec<Vec<usize>> {
    let mut process = Command::new("qhull")
                          .stdin(Stdio::piped())
                          .stdout(Stdio::piped())
                          .arg("d")
                          .arg("i")
                          .spawn()
                          .unwrap_or_else(|e| panic!("couldn't spawn qhull: {:?}", e));

    if let Some(ref mut out) = process.stdin {
        writeln!(out, "2\n{}", ps.len()).unwrap();

        for &Point(x, y) in ps {
            writeln!(out, "{} {}", x, y).unwrap();
        }
    }

    // process.stdout.unwrap().read_to_string(&mut s);
    let output = process.wait_with_output().unwrap();

    let mut lines = Cursor::new(output.stdout).lines();

    let n = lines.next().unwrap().unwrap().parse::<usize>().unwrap();

    let mut res = vec![];

    for line in lines {
        let s = line.unwrap();
        let poly: Vec<usize> = s.split_whitespace().map(|e| e.parse::<usize>().unwrap()).collect();
        res.push(poly);
    }

    assert_eq!(res.len(), n);
    res
}

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

    let seed: u64 = 0;
    let mut rng: MT19937_64 = SeedableRng::from_seed(seed);

    let mut ps = vec![];
    let mut active: Vec<Point> = vec![];

    let r1 = args.flag_r;
    let r2 = 1.;
    let n_gen = 30;

    let h = args.flag_d;
    let mean_dist_ratio = 0.7;

    let k1 = (mean_dist_ratio * 2. * PI * r1 / h).round() as i32;
    let k2 = (mean_dist_ratio * 2. * PI * r2 / h).round() as i32;

    // generate boundary points
    for &(k, r) in &[(k1, r1), (k2, r2)] {
        for i in 0..k {
            let (y, x) = (2. * PI * i as f64 / k as f64).sin_cos();
            ps.push(Point(r * x, r * y));
        }
    }

    // make boundary points active
    active.extend(&ps);

    let n_fixed = ps.len();

    let annulus_dist = AnnulusDist::new(h, 2.0 * h);

    while !active.is_empty() {
        // select a random active point
        let i = rng.gen_range(0, active.len());

        let c = active[i];

        if let Some(p) = annulus_dist.ind_iter(&mut rng)
                                     .map(|p| p + c)
                                     .take(n_gen)
                                     .filter(|&p| {
                                         let d = dist(p, Point(0., 0.));
                                         r1 <= d && d <= r2
                                     })
                                     .filter(|&p| ps.iter().all(|&q| dist(p, q) >= h))
                                     .next() {
            ps.push(p);
            active.push(p);
        } else {
            active.remove(i);
        }

    }

    let indices = qhull_triangulation(&ps);

    let mut neighbors: Vec<Vec<usize>> = ps.iter().map(|_| vec![]).collect();
    for poly in &indices {
        for (&i, &j) in poly.iter().zip(poly.iter().cycle().skip(1)) {
            neighbors[i].push(j);
            neighbors[j].push(i);
        }
    }

    for list in &mut neighbors {
        list.sort();
        list.dedup();
    }

    // Laplace smoothing
    let n_laplace_step = 1;

    let laplace_eps = 1.0e-3;

    for _ in 0..n_laplace_step {
        let mut change = 0.;
        // Gauss-Seidel
        for i in n_fixed..ps.len() {
            let mut x = 0.;
            let mut y = 0.;
            for &j in &neighbors[i] {
                x += ps[j].0;
                y += ps[j].1;
            }
            let n = neighbors[i].len() as f64;
            let p = ps[i];
            let q = Point(x / n, y / n);
            ps[i] = q;
            change += dist_sq(p, q);
        }

        if change.sqrt() < laplace_eps {
            break;
        }
    }

    if !args.flag_no_show {
        let mut fg = Figure::new();
        if let Some(file) = args.flag_plot {
            fg.set_terminal("pngcairo size 720, 720", &file);
        }

        fg.clear_axes();
        {
            let axes = fg.axes2d();
            axes.set_aspect_ratio(Fix(1.));
            for poly in indices {
                axes.lines(poly.iter().cycle().take(poly.len() + 1).map(|&i| ps[i as usize].0),
                           poly.iter().cycle().take(poly.len() + 1).map(|&i| ps[i as usize].1),
                           &[]);
            }
        }

        fg.show();
    }

}
<commit_msg>Simplify point generation<commit_after>//! Uniform point distribution in an annulus using Bridson’s algorithm for
//! Poisson-disc sampling.
//!
//! Bridson, Robert. "Fast Poisson disk sampling in arbitrary dimensions." ACM
//! SIGGRAPH. Vol. 2007. 2007.
//!
//! See also [Visualizing Algorithms](http://bost.ocks.org/mike/algorithms/).
//!
//! Uses [qhull](http://qhull.org/) to generate a Delaunay triangulation.
extern crate docopt;
extern crate rand;
extern crate rustc_serialize;
extern crate gnuplot;
extern crate mersenne_twister;

mod annulus_distribution;

use std::f64::consts::PI;
#[allow(unused_imports)]
use gnuplot::{Figure, Caption, Color, Fix, AxesCommon, PlotOption, DashType, Coordinate, TextColor};
use rand::{Rng, SeedableRng};
use std::io::{Read, Write, Cursor, BufRead};
use std::process::{Command, Stdio};
use docopt::Docopt;
use mersenne_twister::MT19937_64;
use std::ops::Add;
use annulus_distribution::AnnulusDist;

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

static USAGE: &'static str = r"
Simple annulus triangulation generator.

Usage: annulus_mesh [options]
       annulus_mesh (-h | --help | --version)

Options:
    -r INNER        Inner radius [default: 0.2]
    -d DIST         Point distance [default: 0.2]
    -h, --help      Print help
    --plot FILE     Output mesh plot
    --no-show       Do not plot anything
    --version       Print version
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_d: f64,
    flag_r: f64,
    flag_no_show: bool,
    flag_plot: Option<String>,
}

#[derive(Copy, Clone, Debug)]
pub struct Point(f64, f64);

impl Add for Point {
    type Output = Self;

    fn add(self, rhs: Self) -> Self {
        Point(self.0 + rhs.0, self.1 + rhs.1)
    }
}

fn dist_sq(x: Point, y: Point) -> f64 {
    (x.0 - y.0).powi(2) + (x.1 - y.1).powi(2)
}

fn dist(x: Point, y: Point) -> f64 {
    ((x.0 - y.0).powi(2) + (x.1 - y.1).powi(2)).sqrt()
}

fn qhull_triangulation(ps: &[Point]) -> Vec<Vec<usize>> {
    let mut process = Command::new("qhull")
                          .stdin(Stdio::piped())
                          .stdout(Stdio::piped())
                          .arg("d")
                          .arg("i")
                          .spawn()
                          .unwrap_or_else(|e| panic!("couldn't spawn qhull: {:?}", e));

    if let Some(ref mut out) = process.stdin {
        writeln!(out, "2\n{}", ps.len()).unwrap();

        for &Point(x, y) in ps {
            writeln!(out, "{} {}", x, y).unwrap();
        }
    }

    // process.stdout.unwrap().read_to_string(&mut s);
    let output = process.wait_with_output().unwrap();

    let mut lines = Cursor::new(output.stdout).lines();

    let n = lines.next().unwrap().unwrap().parse::<usize>().unwrap();

    let mut res = vec![];

    for line in lines {
        let s = line.unwrap();
        let poly: Vec<usize> = s.split_whitespace().map(|e| e.parse::<usize>().unwrap()).collect();
        res.push(poly);
    }

    assert_eq!(res.len(), n);
    res
}

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

    let seed: u64 = 0;
    let mut rng: MT19937_64 = SeedableRng::from_seed(seed);

    let mut ps = vec![];
    let mut active: Vec<Point> = vec![];

    let r1 = args.flag_r;
    let r2 = 1.;
    let n_gen = 30;

    let h = args.flag_d;
    let mean_dist_ratio = 0.7;

    // generate boundary points
    for &r in &[r1, r2] {
        let k = (mean_dist_ratio * 2. * PI * r / h).round() as i32;
        for i in 0..k {
            let (y, x) = (2. * PI * i as f64 / k as f64).sin_cos();
            ps.push(Point(r * x, r * y));
        }
    }

    // make boundary points active
    active.extend(&ps);

    let n_fixed = ps.len();

    let annulus_dist = AnnulusDist::new(h, 2.0 * h);

    while !active.is_empty() {
        // select a random active point
        let i = rng.gen_range(0, active.len());

        let c = active[i];

        if let Some(p) = annulus_dist.ind_iter(&mut rng)
                                     .map(|p| p + c)
                                     .take(n_gen)
                                     .filter(|&p| {
                                         let d = dist(p, Point(0., 0.));
                                         r1 <= d && d <= r2
                                     })
                                     .filter(|&p| ps.iter().all(|&q| dist(p, q) >= h))
                                     .next() {
            ps.push(p);
            active.push(p);
        } else {
            active.remove(i);
        }

    }

    let indices = qhull_triangulation(&ps);

    let mut neighbors: Vec<Vec<usize>> = ps.iter().map(|_| vec![]).collect();
    for poly in &indices {
        for (&i, &j) in poly.iter().zip(poly.iter().cycle().skip(1)) {
            neighbors[i].push(j);
            neighbors[j].push(i);
        }
    }

    for list in &mut neighbors {
        list.sort();
        list.dedup();
    }

    // Laplace smoothing
    let n_laplace_step = 1;

    let laplace_eps = 1.0e-3;

    for _ in 0..n_laplace_step {
        let mut change = 0.;
        // Gauss-Seidel
        for i in n_fixed..ps.len() {
            let mut x = 0.;
            let mut y = 0.;
            for &j in &neighbors[i] {
                x += ps[j].0;
                y += ps[j].1;
            }
            let n = neighbors[i].len() as f64;
            let p = ps[i];
            let q = Point(x / n, y / n);
            ps[i] = q;
            change += dist_sq(p, q);
        }

        if change.sqrt() < laplace_eps {
            break;
        }
    }

    if !args.flag_no_show {
        let mut fg = Figure::new();
        if let Some(file) = args.flag_plot {
            fg.set_terminal("pngcairo size 720, 720", &file);
        }

        fg.clear_axes();
        {
            let axes = fg.axes2d();
            axes.set_aspect_ratio(Fix(1.));
            for poly in indices {
                axes.lines(poly.iter().cycle().take(poly.len() + 1).map(|&i| ps[i as usize].0),
                           poly.iter().cycle().take(poly.len() + 1).map(|&i| ps[i as usize].1),
                           &[]);
            }
        }

        fg.show();
    }

}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

#[macro_use]
extern crate glium;

extern crate time;

use std::thread;
use std::time::Duration;
use glium::{glutin, DisplayBuild, Surface};
use glium::index::PrimitiveType;

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 2],
    color: [f32; 3],
}

implement_vertex!(Vertex, position, color);

pub enum Action {
    Stop,
    Continue,
}

pub fn start_loop<F>(mut callback: F)
    where F: FnMut() -> Action
{
    let mut accumulator = 0;
    let mut previous_clock = time::precise_time_ns();
    loop {
        match callback() {
            Action::Stop => break,
            Action::Continue => ()
        }
        let now = time::precise_time_ns();
        accumulator += now - previous_clock;
        previous_clock = now;
        const FIXED_TIME_STAMP: u64 = 16666667;
        while accumulator >= FIXED_TIME_STAMP {
            accumulator -= FIXED_TIME_STAMP;
            // if you have a game, update the state here
        }
        thread::sleep(Duration::from_millis(
            ((FIXED_TIME_STAMP - accumulator) / 1000000) as u64));
    }
}

fn make_program(display: &glium::Display) -> glium::Program {
    let api = display.get_window().unwrap().get_api();
    let shader_src_preamble = match api {
        glium::glutin::Api::OpenGl => r"
            #version 120
            #define lowp
            #define mediump
            #define highp
        ",
        glium::glutin::Api::OpenGlEs => r"
            #version 100
        ",
        _ => unimplemented!(),
    }.to_string();
    println!("OZKRIFF: API: {:?}", api);
    let vertex_shader_src = shader_src_preamble.clone() + r"
        uniform lowp mat4 matrix;
        attribute lowp vec2 position;
        attribute lowp vec3 color;
        varying lowp vec3 vColor;
        void main() {
            gl_Position = vec4(position, 0.0, 1.0) * matrix;
            vColor = color;
        }
    ";
    let fragment_shader_src = shader_src_preamble + r"
        varying lowp vec3 vColor;
        void main() {
            gl_FragColor = vec4(vColor, 1.0);
        }
    ";
    let program = glium::Program::from_source(
        display,
        &vertex_shader_src,
        &fragment_shader_src,
        None
    ).unwrap();
    program
}

fn main() {
    std::env::set_var("RUST_BACKTRACE", "1");
    let gl_version = glutin::GlRequest::GlThenGles {
        opengles_version: (2, 0),
        opengl_version: (2, 0)
    };
    let display = glutin::WindowBuilder::new()
        .with_gl(gl_version)
        .with_title("Nergul".to_string())
        .build_glium()
        .unwrap();
    let vertex_buffer = {
        let vertices = [
            Vertex { position: [-0.5, -0.5], color: [0.0, 1.0, 0.0] },
            Vertex { position: [ 0.0,  0.5], color: [0.0, 0.0, 1.0] },
            Vertex { position: [ 0.5, -0.5], color: [1.0, 0.0, 0.0] },
        ];
        glium::VertexBuffer::new(&display, &vertices).unwrap()
    };
    let index_buffer = glium::IndexBuffer::new(
        &display, PrimitiveType::TrianglesList, &[0u16, 1, 2]).unwrap();
    let program = make_program(&display);
    start_loop(|| {
        let uniforms = uniform! {
            matrix: [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0f32],
            ]
        };
        {
            // fn draw() { ...
            let mut target = display.draw();
            target.clear_color(0.0, 0.0, 0.0, 0.0);
            target.draw(
                &vertex_buffer,
                &index_buffer,
                &program,
                &uniforms,
                &Default::default(),
            ).unwrap();
            target.finish().unwrap();
        }
        for event in display.poll_events() {
            match event {
                glutin::Event::Closed => return Action::Stop,
                _ => ()
            }
        }
        Action::Continue
    });
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>main.rs: Added exit on Q/Escape<commit_after>// See LICENSE file for copyright and license details.

#[macro_use]
extern crate glium;

extern crate time;

use std::thread;
use std::time::Duration;
use glium::{glutin, DisplayBuild, Surface};
use glium::index::PrimitiveType;
use glium::glutin::ElementState::{Released};

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 2],
    color: [f32; 3],
}

implement_vertex!(Vertex, position, color);

pub enum Action {
    Stop,
    Continue,
}

pub fn start_loop<F>(mut callback: F)
    where F: FnMut() -> Action
{
    let mut accumulator = 0;
    let mut previous_clock = time::precise_time_ns();
    loop {
        match callback() {
            Action::Stop => break,
            Action::Continue => ()
        }
        let now = time::precise_time_ns();
        accumulator += now - previous_clock;
        previous_clock = now;
        const FIXED_TIME_STAMP: u64 = 16666667;
        while accumulator >= FIXED_TIME_STAMP {
            accumulator -= FIXED_TIME_STAMP;
            // if you have a game, update the state here
        }
        thread::sleep(Duration::from_millis(
            ((FIXED_TIME_STAMP - accumulator) / 1000000) as u64));
    }
}

fn make_program(display: &glium::Display) -> glium::Program {
    let api = display.get_window().unwrap().get_api();
    let shader_src_preamble = match api {
        glium::glutin::Api::OpenGl => r"
            #version 120
            #define lowp
            #define mediump
            #define highp
        ",
        glium::glutin::Api::OpenGlEs => r"
            #version 100
        ",
        _ => unimplemented!(),
    }.to_string();
    println!("OZKRIFF: API: {:?}", api);
    let vertex_shader_src = shader_src_preamble.clone() + r"
        uniform lowp mat4 matrix;
        attribute lowp vec2 position;
        attribute lowp vec3 color;
        varying lowp vec3 vColor;
        void main() {
            gl_Position = vec4(position, 0.0, 1.0) * matrix;
            vColor = color;
        }
    ";
    let fragment_shader_src = shader_src_preamble + r"
        varying lowp vec3 vColor;
        void main() {
            gl_FragColor = vec4(vColor, 1.0);
        }
    ";
    let program = glium::Program::from_source(
        display,
        &vertex_shader_src,
        &fragment_shader_src,
        None
    ).unwrap();
    program
}

fn main() {
    std::env::set_var("RUST_BACKTRACE", "1");
    let gl_version = glutin::GlRequest::GlThenGles {
        opengles_version: (2, 0),
        opengl_version: (2, 0)
    };
    let display = glutin::WindowBuilder::new()
        .with_gl(gl_version)
        .with_title("Nergul".to_string())
        .build_glium()
        .unwrap();
    let vertex_buffer = {
        let vertices = [
            Vertex { position: [-0.5, -0.5], color: [0.0, 1.0, 0.0] },
            Vertex { position: [ 0.0,  0.5], color: [0.0, 0.0, 1.0] },
            Vertex { position: [ 0.5, -0.5], color: [1.0, 0.0, 0.0] },
        ];
        glium::VertexBuffer::new(&display, &vertices).unwrap()
    };
    let index_buffer = glium::IndexBuffer::new(
        &display, PrimitiveType::TrianglesList, &[0u16, 1, 2]).unwrap();
    let program = make_program(&display);
    start_loop(|| {
        let uniforms = uniform! {
            matrix: [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0f32],
            ]
        };
        {
            // fn draw() { ...
            let mut target = display.draw();
            target.clear_color(0.0, 0.0, 0.0, 0.0);
            target.draw(
                &vertex_buffer,
                &index_buffer,
                &program,
                &uniforms,
                &Default::default(),
            ).unwrap();
            target.finish().unwrap();
        }
        for event in display.poll_events() {
            match event {
                glutin::Event::Closed => return Action::Stop,
                glutin::Event::KeyboardInput(Released, _, Some(key)) => {
                    match key {
                        glutin::VirtualKeyCode::Q
                            | glutin::VirtualKeyCode::Escape =>
                        {
                            return Action::Stop;
                        }
                        _ => {},
                    }
                },
                _ => ()
            }
        }
        Action::Continue
    });
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::{fmt, mem};

use bytes::{Bytes, BytesMut};
use futures::{Async, Poll, Stream};

use crate::error::Error;

#[derive(Debug, PartialEq, Copy, Clone)]
/// Different type of body
pub enum BodyLength {
    None,
    Empty,
    Sized(usize),
    Sized64(u64),
    Stream,
}

impl BodyLength {
    pub fn is_eof(&self) -> bool {
        match self {
            BodyLength::None
            | BodyLength::Empty
            | BodyLength::Sized(0)
            | BodyLength::Sized64(0) => true,
            _ => false,
        }
    }
}

/// Type that provides this trait can be streamed to a peer.
pub trait MessageBody {
    fn length(&self) -> BodyLength;

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error>;
}

impl MessageBody for () {
    fn length(&self) -> BodyLength {
        BodyLength::Empty
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        Ok(Async::Ready(None))
    }
}

pub enum ResponseBody<B> {
    Body(B),
    Other(Body),
}

impl ResponseBody<Body> {
    pub fn into_body<B>(self) -> ResponseBody<B> {
        match self {
            ResponseBody::Body(b) => ResponseBody::Other(b),
            ResponseBody::Other(b) => ResponseBody::Other(b),
        }
    }
}

impl<B> ResponseBody<B> {
    pub fn take_body(&mut self) -> ResponseBody<B> {
        std::mem::replace(self, ResponseBody::Other(Body::None))
    }
}

impl<B: MessageBody> ResponseBody<B> {
    pub fn as_ref(&self) -> Option<&B> {
        if let ResponseBody::Body(ref b) = self {
            Some(b)
        } else {
            None
        }
    }
}

impl<B: MessageBody> MessageBody for ResponseBody<B> {
    fn length(&self) -> BodyLength {
        match self {
            ResponseBody::Body(ref body) => body.length(),
            ResponseBody::Other(ref body) => body.length(),
        }
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        match self {
            ResponseBody::Body(ref mut body) => body.poll_next(),
            ResponseBody::Other(ref mut body) => body.poll_next(),
        }
    }
}

/// Represents various types of http message body.
pub enum Body {
    /// Empty response. `Content-Length` header is not set.
    None,
    /// Zero sized response body. `Content-Length` header is set to `0`.
    Empty,
    /// Specific response body.
    Bytes(Bytes),
    /// Generic message body.
    Message(Box<dyn MessageBody>),
}

impl Body {
    /// Create body from slice (copy)
    pub fn from_slice(s: &[u8]) -> Body {
        Body::Bytes(Bytes::from(s))
    }

    /// Create body from generic message body.
    pub fn from_message<B: MessageBody + 'static>(body: B) -> Body {
        Body::Message(Box::new(body))
    }
}

impl MessageBody for Body {
    fn length(&self) -> BodyLength {
        match self {
            Body::None => BodyLength::None,
            Body::Empty => BodyLength::Empty,
            Body::Bytes(ref bin) => BodyLength::Sized(bin.len()),
            Body::Message(ref body) => body.length(),
        }
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        match self {
            Body::None => Ok(Async::Ready(None)),
            Body::Empty => Ok(Async::Ready(None)),
            Body::Bytes(ref mut bin) => {
                let len = bin.len();
                if len == 0 {
                    Ok(Async::Ready(None))
                } else {
                    Ok(Async::Ready(Some(bin.split_to(len))))
                }
            }
            Body::Message(ref mut body) => body.poll_next(),
        }
    }
}

impl PartialEq for Body {
    fn eq(&self, other: &Body) -> bool {
        match *self {
            Body::None => match *other {
                Body::None => true,
                _ => false,
            },
            Body::Empty => match *other {
                Body::Empty => true,
                _ => false,
            },
            Body::Bytes(ref b) => match *other {
                Body::Bytes(ref b2) => b == b2,
                _ => false,
            },
            Body::Message(_) => false,
        }
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Body::None => write!(f, "Body::None"),
            Body::Empty => write!(f, "Body::Zero"),
            Body::Bytes(ref b) => write!(f, "Body::Bytes({:?})", b),
            Body::Message(_) => write!(f, "Body::Message(_)"),
        }
    }
}

impl From<&'static str> for Body {
    fn from(s: &'static str) -> Body {
        Body::Bytes(Bytes::from_static(s.as_ref()))
    }
}

impl From<&'static [u8]> for Body {
    fn from(s: &'static [u8]) -> Body {
        Body::Bytes(Bytes::from_static(s))
    }
}

impl From<Vec<u8>> for Body {
    fn from(vec: Vec<u8>) -> Body {
        Body::Bytes(Bytes::from(vec))
    }
}

impl From<String> for Body {
    fn from(s: String) -> Body {
        s.into_bytes().into()
    }
}

impl<'a> From<&'a String> for Body {
    fn from(s: &'a String) -> Body {
        Body::Bytes(Bytes::from(AsRef::<[u8]>::as_ref(&s)))
    }
}

impl From<Bytes> for Body {
    fn from(s: Bytes) -> Body {
        Body::Bytes(s)
    }
}

impl From<BytesMut> for Body {
    fn from(s: BytesMut) -> Body {
        Body::Bytes(s.freeze())
    }
}

impl MessageBody for Bytes {
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.len())
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        if self.is_empty() {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::Ready(Some(mem::replace(self, Bytes::new()))))
        }
    }
}

impl MessageBody for BytesMut {
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.len())
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        if self.is_empty() {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::Ready(Some(
                mem::replace(self, BytesMut::new()).freeze(),
            )))
        }
    }
}

impl MessageBody for &'static str {
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.len())
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        if self.is_empty() {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::Ready(Some(Bytes::from_static(
                mem::replace(self, "").as_ref(),
            ))))
        }
    }
}

impl MessageBody for &'static [u8] {
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.len())
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        if self.is_empty() {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::Ready(Some(Bytes::from_static(mem::replace(
                self, b"",
            )))))
        }
    }
}

impl MessageBody for Vec<u8> {
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.len())
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        if self.is_empty() {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::Ready(Some(Bytes::from(mem::replace(
                self,
                Vec::new(),
            )))))
        }
    }
}

impl MessageBody for String {
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.len())
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        if self.is_empty() {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::Ready(Some(Bytes::from(
                mem::replace(self, String::new()).into_bytes(),
            ))))
        }
    }
}

/// Type represent streaming body.
/// Response does not contain `content-length` header and appropriate transfer encoding is used.
pub struct BodyStream<S, E> {
    stream: S,
    _t: PhantomData<E>,
}

impl<S, E> BodyStream<S, E>
where
    S: Stream<Item = Bytes, Error = E>,
    E: Into<Error>,
{
    pub fn new(stream: S) -> Self {
        BodyStream {
            stream,
            _t: PhantomData,
        }
    }
}

impl<S, E> MessageBody for BodyStream<S, E>
where
    S: Stream<Item = Bytes, Error = E>,
    E: Into<Error>,
{
    fn length(&self) -> BodyLength {
        BodyLength::Stream
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        self.stream.poll().map_err(|e| e.into())
    }
}

/// Type represent streaming body. This body implementation should be used
/// if total size of stream is known. Data get sent as is without using transfer encoding.
pub struct SizedStream<S> {
    size: usize,
    stream: S,
}

impl<S> SizedStream<S>
where
    S: Stream<Item = Bytes, Error = Error>,
{
    pub fn new(size: usize, stream: S) -> Self {
        SizedStream { size, stream }
    }
}

impl<S> MessageBody for SizedStream<S>
where
    S: Stream<Item = Bytes, Error = Error>,
{
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.size)
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        self.stream.poll()
    }
}

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

    impl Body {
        pub(crate) fn get_ref(&self) -> &[u8] {
            match *self {
                Body::Bytes(ref bin) => &bin,
                _ => panic!(),
            }
        }
    }

    impl ResponseBody<Body> {
        pub(crate) fn get_ref(&self) -> &[u8] {
            match *self {
                ResponseBody::Body(ref b) => b.get_ref(),
                ResponseBody::Other(ref b) => b.get_ref(),
            }
        }
    }

    #[test]
    fn test_static_str() {
        assert_eq!(Body::from("").length(), BodyLength::Sized(0));
        assert_eq!(Body::from("test").length(), BodyLength::Sized(4));
        assert_eq!(Body::from("test").get_ref(), b"test");
    }

    #[test]
    fn test_static_bytes() {
        assert_eq!(Body::from(b"test".as_ref()).length(), BodyLength::Sized(4));
        assert_eq!(Body::from(b"test".as_ref()).get_ref(), b"test");
        assert_eq!(
            Body::from_slice(b"test".as_ref()).length(),
            BodyLength::Sized(4)
        );
        assert_eq!(Body::from_slice(b"test".as_ref()).get_ref(), b"test");
    }

    #[test]
    fn test_vec() {
        assert_eq!(Body::from(Vec::from("test")).length(), BodyLength::Sized(4));
        assert_eq!(Body::from(Vec::from("test")).get_ref(), b"test");
    }

    #[test]
    fn test_bytes() {
        assert_eq!(
            Body::from(Bytes::from("test")).length(),
            BodyLength::Sized(4)
        );
        assert_eq!(Body::from(Bytes::from("test")).get_ref(), b"test");
    }

    #[test]
    fn test_string() {
        let b = "test".to_owned();
        assert_eq!(Body::from(b.clone()).length(), BodyLength::Sized(4));
        assert_eq!(Body::from(b.clone()).get_ref(), b"test");
        assert_eq!(Body::from(&b).length(), BodyLength::Sized(4));
        assert_eq!(Body::from(&b).get_ref(), b"test");
    }

    #[test]
    fn test_bytes_mut() {
        let b = BytesMut::from("test");
        assert_eq!(Body::from(b.clone()).length(), BodyLength::Sized(4));
        assert_eq!(Body::from(b).get_ref(), b"test");
    }
}
<commit_msg>add Stream impl for ResponseBody<commit_after>use std::marker::PhantomData;
use std::{fmt, mem};

use bytes::{Bytes, BytesMut};
use futures::{Async, Poll, Stream};

use crate::error::Error;

#[derive(Debug, PartialEq, Copy, Clone)]
/// Different type of body
pub enum BodyLength {
    None,
    Empty,
    Sized(usize),
    Sized64(u64),
    Stream,
}

impl BodyLength {
    pub fn is_eof(&self) -> bool {
        match self {
            BodyLength::None
            | BodyLength::Empty
            | BodyLength::Sized(0)
            | BodyLength::Sized64(0) => true,
            _ => false,
        }
    }
}

/// Type that provides this trait can be streamed to a peer.
pub trait MessageBody {
    fn length(&self) -> BodyLength;

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error>;
}

impl MessageBody for () {
    fn length(&self) -> BodyLength {
        BodyLength::Empty
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        Ok(Async::Ready(None))
    }
}

pub enum ResponseBody<B> {
    Body(B),
    Other(Body),
}

impl ResponseBody<Body> {
    pub fn into_body<B>(self) -> ResponseBody<B> {
        match self {
            ResponseBody::Body(b) => ResponseBody::Other(b),
            ResponseBody::Other(b) => ResponseBody::Other(b),
        }
    }
}

impl<B> ResponseBody<B> {
    pub fn take_body(&mut self) -> ResponseBody<B> {
        std::mem::replace(self, ResponseBody::Other(Body::None))
    }
}

impl<B: MessageBody> ResponseBody<B> {
    pub fn as_ref(&self) -> Option<&B> {
        if let ResponseBody::Body(ref b) = self {
            Some(b)
        } else {
            None
        }
    }
}

impl<B: MessageBody> MessageBody for ResponseBody<B> {
    fn length(&self) -> BodyLength {
        match self {
            ResponseBody::Body(ref body) => body.length(),
            ResponseBody::Other(ref body) => body.length(),
        }
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        match self {
            ResponseBody::Body(ref mut body) => body.poll_next(),
            ResponseBody::Other(ref mut body) => body.poll_next(),
        }
    }
}

impl<B: MessageBody> Stream for ResponseBody<B> {
    type Item = Bytes;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        self.poll_next()
    }
}

/// Represents various types of http message body.
pub enum Body {
    /// Empty response. `Content-Length` header is not set.
    None,
    /// Zero sized response body. `Content-Length` header is set to `0`.
    Empty,
    /// Specific response body.
    Bytes(Bytes),
    /// Generic message body.
    Message(Box<dyn MessageBody>),
}

impl Body {
    /// Create body from slice (copy)
    pub fn from_slice(s: &[u8]) -> Body {
        Body::Bytes(Bytes::from(s))
    }

    /// Create body from generic message body.
    pub fn from_message<B: MessageBody + 'static>(body: B) -> Body {
        Body::Message(Box::new(body))
    }
}

impl MessageBody for Body {
    fn length(&self) -> BodyLength {
        match self {
            Body::None => BodyLength::None,
            Body::Empty => BodyLength::Empty,
            Body::Bytes(ref bin) => BodyLength::Sized(bin.len()),
            Body::Message(ref body) => body.length(),
        }
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        match self {
            Body::None => Ok(Async::Ready(None)),
            Body::Empty => Ok(Async::Ready(None)),
            Body::Bytes(ref mut bin) => {
                let len = bin.len();
                if len == 0 {
                    Ok(Async::Ready(None))
                } else {
                    Ok(Async::Ready(Some(bin.split_to(len))))
                }
            }
            Body::Message(ref mut body) => body.poll_next(),
        }
    }
}

impl PartialEq for Body {
    fn eq(&self, other: &Body) -> bool {
        match *self {
            Body::None => match *other {
                Body::None => true,
                _ => false,
            },
            Body::Empty => match *other {
                Body::Empty => true,
                _ => false,
            },
            Body::Bytes(ref b) => match *other {
                Body::Bytes(ref b2) => b == b2,
                _ => false,
            },
            Body::Message(_) => false,
        }
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Body::None => write!(f, "Body::None"),
            Body::Empty => write!(f, "Body::Zero"),
            Body::Bytes(ref b) => write!(f, "Body::Bytes({:?})", b),
            Body::Message(_) => write!(f, "Body::Message(_)"),
        }
    }
}

impl From<&'static str> for Body {
    fn from(s: &'static str) -> Body {
        Body::Bytes(Bytes::from_static(s.as_ref()))
    }
}

impl From<&'static [u8]> for Body {
    fn from(s: &'static [u8]) -> Body {
        Body::Bytes(Bytes::from_static(s))
    }
}

impl From<Vec<u8>> for Body {
    fn from(vec: Vec<u8>) -> Body {
        Body::Bytes(Bytes::from(vec))
    }
}

impl From<String> for Body {
    fn from(s: String) -> Body {
        s.into_bytes().into()
    }
}

impl<'a> From<&'a String> for Body {
    fn from(s: &'a String) -> Body {
        Body::Bytes(Bytes::from(AsRef::<[u8]>::as_ref(&s)))
    }
}

impl From<Bytes> for Body {
    fn from(s: Bytes) -> Body {
        Body::Bytes(s)
    }
}

impl From<BytesMut> for Body {
    fn from(s: BytesMut) -> Body {
        Body::Bytes(s.freeze())
    }
}

impl MessageBody for Bytes {
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.len())
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        if self.is_empty() {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::Ready(Some(mem::replace(self, Bytes::new()))))
        }
    }
}

impl MessageBody for BytesMut {
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.len())
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        if self.is_empty() {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::Ready(Some(
                mem::replace(self, BytesMut::new()).freeze(),
            )))
        }
    }
}

impl MessageBody for &'static str {
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.len())
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        if self.is_empty() {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::Ready(Some(Bytes::from_static(
                mem::replace(self, "").as_ref(),
            ))))
        }
    }
}

impl MessageBody for &'static [u8] {
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.len())
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        if self.is_empty() {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::Ready(Some(Bytes::from_static(mem::replace(
                self, b"",
            )))))
        }
    }
}

impl MessageBody for Vec<u8> {
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.len())
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        if self.is_empty() {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::Ready(Some(Bytes::from(mem::replace(
                self,
                Vec::new(),
            )))))
        }
    }
}

impl MessageBody for String {
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.len())
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        if self.is_empty() {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::Ready(Some(Bytes::from(
                mem::replace(self, String::new()).into_bytes(),
            ))))
        }
    }
}

/// Type represent streaming body.
/// Response does not contain `content-length` header and appropriate transfer encoding is used.
pub struct BodyStream<S, E> {
    stream: S,
    _t: PhantomData<E>,
}

impl<S, E> BodyStream<S, E>
where
    S: Stream<Item = Bytes, Error = E>,
    E: Into<Error>,
{
    pub fn new(stream: S) -> Self {
        BodyStream {
            stream,
            _t: PhantomData,
        }
    }
}

impl<S, E> MessageBody for BodyStream<S, E>
where
    S: Stream<Item = Bytes, Error = E>,
    E: Into<Error>,
{
    fn length(&self) -> BodyLength {
        BodyLength::Stream
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        self.stream.poll().map_err(|e| e.into())
    }
}

/// Type represent streaming body. This body implementation should be used
/// if total size of stream is known. Data get sent as is without using transfer encoding.
pub struct SizedStream<S> {
    size: usize,
    stream: S,
}

impl<S> SizedStream<S>
where
    S: Stream<Item = Bytes, Error = Error>,
{
    pub fn new(size: usize, stream: S) -> Self {
        SizedStream { size, stream }
    }
}

impl<S> MessageBody for SizedStream<S>
where
    S: Stream<Item = Bytes, Error = Error>,
{
    fn length(&self) -> BodyLength {
        BodyLength::Sized(self.size)
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        self.stream.poll()
    }
}

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

    impl Body {
        pub(crate) fn get_ref(&self) -> &[u8] {
            match *self {
                Body::Bytes(ref bin) => &bin,
                _ => panic!(),
            }
        }
    }

    impl ResponseBody<Body> {
        pub(crate) fn get_ref(&self) -> &[u8] {
            match *self {
                ResponseBody::Body(ref b) => b.get_ref(),
                ResponseBody::Other(ref b) => b.get_ref(),
            }
        }
    }

    #[test]
    fn test_static_str() {
        assert_eq!(Body::from("").length(), BodyLength::Sized(0));
        assert_eq!(Body::from("test").length(), BodyLength::Sized(4));
        assert_eq!(Body::from("test").get_ref(), b"test");
    }

    #[test]
    fn test_static_bytes() {
        assert_eq!(Body::from(b"test".as_ref()).length(), BodyLength::Sized(4));
        assert_eq!(Body::from(b"test".as_ref()).get_ref(), b"test");
        assert_eq!(
            Body::from_slice(b"test".as_ref()).length(),
            BodyLength::Sized(4)
        );
        assert_eq!(Body::from_slice(b"test".as_ref()).get_ref(), b"test");
    }

    #[test]
    fn test_vec() {
        assert_eq!(Body::from(Vec::from("test")).length(), BodyLength::Sized(4));
        assert_eq!(Body::from(Vec::from("test")).get_ref(), b"test");
    }

    #[test]
    fn test_bytes() {
        assert_eq!(
            Body::from(Bytes::from("test")).length(),
            BodyLength::Sized(4)
        );
        assert_eq!(Body::from(Bytes::from("test")).get_ref(), b"test");
    }

    #[test]
    fn test_string() {
        let b = "test".to_owned();
        assert_eq!(Body::from(b.clone()).length(), BodyLength::Sized(4));
        assert_eq!(Body::from(b.clone()).get_ref(), b"test");
        assert_eq!(Body::from(&b).length(), BodyLength::Sized(4));
        assert_eq!(Body::from(&b).get_ref(), b"test");
    }

    #[test]
    fn test_bytes_mut() {
        let b = BytesMut::from("test");
        assert_eq!(Body::from(b.clone()).length(), BodyLength::Sized(4));
        assert_eq!(Body::from(b).get_ref(), b"test");
    }
}
<|endoftext|>