<commit_before>#![feature(plugin)]
#![plugin(clippy)]
// #![deny(clippy_pedantic)]
extern crate termion;
extern crate serde_json;
#[macro_use]
extern crate log;
extern crate log4rs;

mod core;

use termion::{clear, cursor};
use termion::raw::IntoRawMode;
use termion::input::TermRead;
use std::io::{stdout, Write, stdin};
use std::sync::mpsc;
use std::{thread, time};
use core::Core;

struct Screen {
    stdout: termion::raw::RawTerminal<std::io::Stdout>,
    size: (u16, u16),
}

impl Screen {

    fn new() -> Screen {
        let mut stdout = stdout().into_raw_mode().unwrap();
        write!(stdout, "{}", clear::All).unwrap();
        stdout.flush().unwrap();
        Screen {
            size: termion::terminal_size().unwrap(),
            stdout: stdout,
        }
    }

    // TODO: handle lines that are longer than terminal width.
    // Should we wrap them or truncate them?
    fn redraw(&mut self, update: &Update) {
        write!(self.stdout, "{}", termion::clear::All).unwrap();
        write!(self.stdout, "{}", cursor::Up(self.size.1)).unwrap();

        let nb_lines = update.lines.len();
        if nb_lines > 0 {
            for line in update.lines.iter().take(nb_lines - 1) {
                write!(self.stdout, "{}", cursor::Left(self.size.0)).unwrap();
                self.stdout.write_all(line.text.as_bytes()).unwrap();
            }

            // If the last line has a trailing \n, we need to remove it
            let mut last_line = update.lines[nb_lines - 1].text.clone();
            match last_line.pop() {
                Some('\n') | None => {
                },
                Some(c) => {
                    last_line.push(c);
                }
            }
            write!(self.stdout, "{}", cursor::Left(self.size.0)).unwrap();
            self.stdout.write_all(last_line.as_bytes()).unwrap();
        }

        write!(self.stdout, "{}", cursor::Goto(
                // columns
                update.scroll_to.1 as u16 + 1,
                // lines
                (update.scroll_to.0 - update.first_line + 1) as u16)).unwrap();
        self.stdout.flush().unwrap();
    }

    fn init(&mut self) {
        write!(self.stdout, "{}", termion::clear::All).unwrap();
        write!(self.stdout, "{}", cursor::Up(self.size.1)).unwrap();
        self.stdout.flush().unwrap();
    }

}

struct Update {
    lines: Vec<Line>,
    height: u64,
    scroll_to: (u64, u64),
    first_line: u64
}

impl Update {
    fn from_value(value: &serde_json::Value) -> Update {
        let object = value.as_object().unwrap();
        let scroll_to = object.get("scrollto").unwrap().as_array().unwrap();
        let mut lines: Vec<Line> = vec![];
        for line in object.get("lines").unwrap().as_array().unwrap().iter() {
            lines.push(Line::from_value(line));
        }
        Update {
            height: object.get("height").unwrap().as_u64().unwrap(),
            first_line: object.get("first_line").unwrap().as_u64().unwrap(),
            lines: lines,
            scroll_to: (scroll_to[0].as_u64().unwrap(), scroll_to[1].as_u64().unwrap()),
        }
    }
}

struct Line {
    text: String,
    selection: Option<(u64, u64)>,
    cursor: Option<u64>,
}

impl Line {
    fn from_value(value: &serde_json::Value) -> Line {
        let line_arr = value.as_array().unwrap();
        let mut line = Line {
            text: line_arr[0].as_str().unwrap().to_string(),
            cursor: None,
            selection: None,
        };
        for annotation in line_arr.iter().skip(1).map(|a| a.as_array().unwrap()) {
            match annotation[0].as_str().unwrap() {
                "cursor" => {
                    line.cursor = Some(annotation[1].as_u64().unwrap());
                },
                "sel" => {
                    line.selection = Some((annotation[1].as_u64().unwrap(), annotation[2].as_u64().unwrap()));
                },
                _ => {
                    error!("unknown annotation");
                }
            }
        }
        line
    }
}

fn update_screen(core: &mut Core, screen: &mut Screen) {
    // TODO: check if terminal size changed. If so, send a `render_line` command to the backend,
    // and a `scroll` command for future updates.
    if let Ok(msg) = core.update_rx.try_recv() {
        let update = Update::from_value(msg.as_object().unwrap().get("update").unwrap());
        screen.redraw(&update);
    } else {
        thread::sleep(time::Duration::from_millis(10));
    }
}

pub struct Input {
    tx: mpsc::Sender<termion::event::Event>,
    rx: mpsc::Receiver<termion::event::Event>,
}

impl Input {
    pub fn new() -> Input {
        let (tx, rx) = mpsc::channel();
        Input {
            tx: tx,
            rx: rx,
        }
    }

    pub fn run(&mut self) {
        let tx = self.tx.clone();
        thread::spawn(move || {
            for event_res in stdin().events() {
                match event_res {
                    Ok(event) => {
                        tx.send(event).unwrap();
                    },
                    Err(err) => {
                        error!("{:?}", err);
                    }
                }
            }
        });
    }
}

impl Default for Input {
	fn default() -> Self {
		Self::new()
	}
}

fn main() {
    log4rs::init_file("log_config.yaml", Default::default()).unwrap();
    let mut core = Core::new("../xi-editor/rust/target/debug/xi-core");
    let mut screen = Screen::new();
    let mut input = Input::new();
    input.run();
    screen.init();
    core.scroll(0, screen.size.1 as u64 - 2);

    let mut current_file: Option<String> = None;
    if let Some(filename) = std::env::args().nth(1) {
        core.open(filename.as_str());
        current_file = Some(filename);
    }

    loop {
        if let Ok(event) = input.rx.try_recv() {
            match event {
                termion::event::Event::Key(key) => {
                    match key {
                        termion::event::Key::Char(c) => {
                            core.char(c);
                        },
                        termion::event::Key::Ctrl(c) => {
                            match c {
                                'c' => {
                                    info!("received ^C: exiting");
                                    return;
                                },
                                'w' => {
                                    info!("received ^W: writing current file");
                                    if let Some(ref filename) = current_file {
                                        core.save(filename.as_str());
                                    } else {
                                        error!("no file to save");
                                    }
                                },
                                _ => {}
                            }
                        },
                        termion::event::Key::Backspace => {
                            core.del();
                        },
                        termion::event::Key::Left => {
                            core.left();
                        },
                        termion::event::Key::Right => {
                            core.right();
                        },
                        termion::event::Key::Up => {
                            core.up();
                        },
                        termion::event::Key::Down => {
                            core.down();
                        },
                        _ => {
                            error!("unsupported key event");
                        }
                    }
                },
                termion::event::Event::Mouse(_) => {
                    error!("mouse events are not supported yet");
                }
                _ => {
                    error!("unsupported event");
                }
            }
        } else {
            update_screen(&mut core, &mut screen);
        }
    }
}
<commit_msg>fix scrolling, and add page up/down<commit_after>#![feature(plugin)]
#![plugin(clippy)]
// #![deny(clippy_pedantic)]
extern crate termion;
extern crate serde_json;
#[macro_use]
extern crate log;
extern crate log4rs;

mod core;

use termion::{clear, cursor};
use termion::raw::IntoRawMode;
use termion::input::TermRead;
use std::io::{stdout, Write, stdin};
use std::sync::mpsc;
use std::{thread, time, env, cmp};
use core::Core;

struct Screen {
    stdout: termion::raw::RawTerminal<std::io::Stdout>,
    size: (u16, u16),
}

impl Screen {

    fn new() -> Screen {
        let mut stdout = stdout().into_raw_mode().unwrap();
        write!(stdout, "{}", clear::All).unwrap();
        stdout.flush().unwrap();
        Screen {
            size: termion::terminal_size().unwrap(),
            stdout: stdout,
        }
    }

    // TODO: handle lines that are longer than terminal width.
    // Should we wrap them or truncate them?
    fn redraw(&mut self, update: &Update) {
        write!(self.stdout, "{}", termion::clear::All).unwrap();
        write!(self.stdout, "{}", cursor::Up(self.size.1)).unwrap();

        let nb_lines = cmp::min(update.lines.len(), self.size.1 as usize);
        if nb_lines > 0 {
            for line in update.lines.iter().take(nb_lines - 1) {
                write!(self.stdout, "{}", cursor::Left(self.size.0)).unwrap();
                self.stdout.write_all(line.text.as_bytes()).unwrap();
            }

            // If the last line has a trailing \n, we need to remove it
            let mut last_line = update.lines[nb_lines - 1].text.clone();
            match last_line.pop() {
                Some('\n') | None => {
                },
                Some(c) => {
                    last_line.push(c);
                }
            }
            write!(self.stdout, "{}", cursor::Left(self.size.0)).unwrap();
            self.stdout.write_all(last_line.as_bytes()).unwrap();
        }

        write!(self.stdout, "{}", cursor::Goto(
                // columns
                update.scroll_to.1 as u16 + 1,
                // lines
                (update.scroll_to.0 - update.first_line + 1) as u16)).unwrap();
        self.stdout.flush().unwrap();
    }

    fn init(&mut self) {
        write!(self.stdout, "{}", termion::clear::All).unwrap();
        write!(self.stdout, "{}", cursor::Up(self.size.1)).unwrap();
        self.stdout.flush().unwrap();
    }

}

struct Update {
    lines: Vec<Line>,
    height: u64,
    scroll_to: (u64, u64),
    first_line: u64
}

impl Update {
    fn from_value(value: &serde_json::Value) -> Update {
        let object = value.as_object().unwrap();
        let scroll_to = object.get("scrollto").unwrap().as_array().unwrap();
        let mut lines: Vec<Line> = vec![];
        for line in object.get("lines").unwrap().as_array().unwrap().iter() {
            lines.push(Line::from_value(line));
        }
        Update {
            height: object.get("height").unwrap().as_u64().unwrap(),
            first_line: object.get("first_line").unwrap().as_u64().unwrap(),
            lines: lines,
            scroll_to: (scroll_to[0].as_u64().unwrap(), scroll_to[1].as_u64().unwrap()),
        }
    }
}

struct Line {
    text: String,
    selection: Option<(u64, u64)>,
    cursor: Option<u64>,
}

impl Line {
    fn from_value(value: &serde_json::Value) -> Line {
        let line_arr = value.as_array().unwrap();
        let mut line = Line {
            text: line_arr[0].as_str().unwrap().to_string(),
            cursor: None,
            selection: None,
        };
        for annotation in line_arr.iter().skip(1).map(|a| a.as_array().unwrap()) {
            match annotation[0].as_str().unwrap() {
                "cursor" => {
                    line.cursor = Some(annotation[1].as_u64().unwrap());
                },
                "sel" => {
                    line.selection = Some((annotation[1].as_u64().unwrap(), annotation[2].as_u64().unwrap()));
                },
                _ => {
                    error!("unknown annotation");
                }
            }
        }
        line
    }
}

fn update_screen(core: &mut Core, screen: &mut Screen) {
    // TODO: check if terminal size changed. If so, send a `render_line` command to the backend,
    // and a `scroll` command for future updates.
    if let Ok(msg) = core.update_rx.try_recv() {
        let update = Update::from_value(msg.as_object().unwrap().get("update").unwrap());
        screen.redraw(&update);
    } else {
        thread::sleep(time::Duration::from_millis(10));
    }
}

pub struct Input {
    tx: mpsc::Sender<termion::event::Event>,
    rx: mpsc::Receiver<termion::event::Event>,
}

impl Input {
    pub fn new() -> Input {
        let (tx, rx) = mpsc::channel();
        Input {
            tx: tx,
            rx: rx,
        }
    }

    pub fn run(&mut self) {
        let tx = self.tx.clone();
        thread::spawn(move || {
            for event_res in stdin().events() {
                match event_res {
                    Ok(event) => {
                        tx.send(event).unwrap();
                    },
                    Err(err) => {
                        error!("{:?}", err);
                    }
                }
            }
        });
    }
}

impl Default for Input {
	fn default() -> Self {
		Self::new()
	}
}

fn main() {
    log4rs::init_file("log_config.yaml", Default::default()).unwrap();
    let mut core = Core::new("../xi-editor/rust/target/debug/xi-core");
    let mut screen = Screen::new();
    let mut input = Input::new();
    input.run();
    screen.init();
    core.scroll(0, screen.size.1 as u64 - 2);

    let mut current_file: Option<String> = None;
    if let Some(filename) = env::args().nth(1) {
        core.open(filename.as_str());
        current_file = Some(filename);
    }

    loop {
        if let Ok(event) = input.rx.try_recv() {
            match event {
                termion::event::Event::Key(key) => {
                    match key {
                        termion::event::Key::Char(c) => {
                            core.char(c);
                        },
                        termion::event::Key::Ctrl(c) => {
                            match c {
                                'c' => {
                                    info!("received ^C: exiting");
                                    return;
                                },
                                'w' => {
                                    info!("received ^W: writing current file");
                                    if let Some(ref filename) = current_file {
                                        core.save(filename.as_str());
                                    } else {
                                        error!("no file to save");
                                    }
                                },
                                _ => {}
                            }
                        },
                        termion::event::Key::Backspace => {
                            core.del();
                        },
                        termion::event::Key::Left => {
                            core.left();
                        },
                        termion::event::Key::Right => {
                            core.right();
                        },
                        termion::event::Key::Up => {
                            core.up();
                        },
                        termion::event::Key::Down => {
                            core.down();
                        },
                        termion::event::Key::PageUp => {
                            core.page_up();
                        },
                        termion::event::Key::PageDown => {
                            core.page_down();
                        },
                        _ => {
                            error!("unsupported key event");
                        }
                    }
                },
                termion::event::Event::Mouse(_) => {
                    error!("mouse events are not supported yet");
                }
                _ => {
                    error!("unsupported event");
                }
            }
        } else {
            update_screen(&mut core, &mut screen);
        }
    }
}
<|endoftext|>


<commit_before>extern crate brotli;

use std::io::Read;
use brotli::Decompressor;

fn main() {
	let mut input = vec![];
	let res = Decompressor::new(std::fs::File::open("id:000012,src:000128,op:havoc,rep:4").unwrap()).read_to_end(&mut input);

	println!("output length = {:?}", input.len());
	println!("res = {:?}", res);
}<commit_msg>MOD: main now automatically goes through afl-findings to check on possible crashes and hangs<commit_after>extern crate brotli;

use std::io;
use std::io::Read;
use brotli::Decompressor;
use std::fs;
use std::path::Path;

fn visit_dirs(dir: &Path) -> io::Result<()> {
    if try!(fs::metadata(dir)).is_dir() {
        for entry in try!(fs::read_dir(dir)) {
            let entry = try!(entry);
            if try!(fs::metadata(entry.path())).is_dir() {
                ;
            } else {
            	if entry.file_name().to_str().unwrap().starts_with("id") {
            		println!("{:?}:", &entry.path());
            		let mut input = Vec::new();
					let res = Decompressor::new(std::fs::File::open(&entry.path()).unwrap()).read_to_end(&mut input);

					println!("output length = {:?}", input.len());
					println!("res = {:?}\n===========\n", res);
            	}

            }
        }
    }
    Ok(())
}

fn main() {

	let _ = visit_dirs(Path::new("afl-findings/crashes"));
	let _ = visit_dirs(Path::new("afl-findings/hangs"));
}<|endoftext|>


<commit_before>use std::fs::File;
use std::io::BufWriter;
use std::io::Write;
use std::io::BufReader;
use std::io::Read;

extern crate modfile;
use modfile::ptmf;

extern crate rustc_serialize;
extern crate docopt;
use docopt::Docopt;

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

static USAGE: &'static str = "
mod2abc.

Usage:
    mod2abc (-h | --help)
    mod2abc (-V | --version)
    mod2abc --in=<filename> --out=<filename> [--format-jbe]

Options:
    -V, --version         Show version info.
    -h, --help            Show this text.
	--in=<filename>       Name of inputfile
	--out=<filename>      Name of outputfile
	--format-jbe          Use format for jbe replay
";

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

	flag_in: String,
	flag_out: String,
	flag_format_jbe: bool
}

fn note_from_period(period: u16) -> String {
	// Find the position in PERIODS with the
	// smallest difference
	let mut found:i32 = -1;
	let mut min_diff = 65536;
	let key = period as i32;
	for i in 0..ptmf::PERIODS.len() {
		let diff = (key as i32 - ptmf::PERIODS[i] as i32).abs();
		if diff < min_diff {
			min_diff = diff;
			found = i as i32;
		}
	}

	let note = if found == -1 {
		println!("Failed to find note name");
		String::new()
	} else {
		let octave = found / 12;
		let name = ptmf::NOTE_NAMES[(found % 12) as usize];
		if octave == 2 {
			// Lower case
			name.to_lowercase()
		} else if octave == 3 {
			// Upper case
			name.to_uppercase()
		} else {
			format!("O{}{}",octave,name)
		}
	};

	note
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
//    println!("{:?}", args);

	if args.flag_version {
		println!("Version: {}", VERSION);
		return;
	}

	if args.flag_in == "" {
		println!("No inputfile specificed");
		return
	}

	if args.flag_out == "" {
		println!("No outputfile specificed");
		return
	}

	let ref input_filename = args.flag_in;
	let file = match File::open(input_filename) {
		Ok(file) => file,
		Err(e) => {
			println!("Failed to open file: '{}' Error: '{}'", input_filename, e);
			return
		}
	};

	let read_fn:fn (&mut Read) -> Result<ptmf::PTModule, ptmf::PTMFError> = ptmf::read_mod;

	let mut reader = BufReader::new(&file);
	let module = match read_fn(&mut reader) {
		Ok(module) => module,
		Err(e) => {
			println!("Failed to parse file: '{}' Error: '{:?}'", input_filename, e);
			return;
		}
	};

	let ref output_filename = args.flag_out;
	let file = match File::create(&output_filename) {
		Ok(file) => file,
		Err(e) => {
			println!("Failed to open file: '{}' Error: '{:?}'", output_filename, e);
			return
		}
	};

	let mut writer = BufWriter::new(&file);

	if args.flag_format_jbe {
		// Write in which order to play patterns
		write!(writer, "song\n").unwrap();
		write!(writer, "{{\n\t").unwrap();
		for i in 0..module.length {
			let position = module.positions.data[i as usize];
			if i == 0 {
				write!(writer, "{}", position).unwrap();
			} else {
				write!(writer, ",{}", position).unwrap();
			}
		}
		write!(writer, "\n}}\n").unwrap();

		// Write patterns
		write!(writer, "patterns\n").unwrap();
		write!(writer, "{{\n").unwrap();
		let mut pattern_no = 0;
		for pattern in module.patterns {
			write!(writer,"\t{}:", pattern_no).unwrap();
			// Loop through the pattern three times
			// 0 = just sample number
			// 1,2 = just pitch
			let mut row_no = 0;
			for row in &pattern.rows {
				let ref channel = row.channels[0];
				if row_no != 0 {
					write!(writer,",").unwrap();
				}
				if channel.sample_number > 0 {
					let number = channel.sample_number as i8;
					write!(writer,"S{}", number).unwrap();
				}
				row_no += 1;
			}
			write!(writer,"\n").unwrap();

			write!(writer,"\t{}:", pattern_no).unwrap();
			row_no = 0;
			for row in &pattern.rows {
				let ref channel = row.channels[1];
				if row_no != 0 {
					write!(writer,",").unwrap();
				}
				if channel.period > 0 {
					let note = note_from_period(channel.period);
					write!(writer,"{}", note).unwrap();
				}
				row_no += 1;
			}
			write!(writer,"\n").unwrap();

			write!(writer,"\t{}:", pattern_no).unwrap();
			row_no = 0;
			for row in &pattern.rows {
				let ref channel = row.channels[2];
				if row_no != 0 {
					write!(writer,",").unwrap();
				}
				if channel.period > 0 {
					let note = note_from_period(channel.period);
					write!(writer,"{}", note).unwrap();
				}
				row_no += 1;
			}
			write!(writer,"\n").unwrap();

			write!(writer,"\n").unwrap();
			pattern_no += 1;
		}
		write!(writer, "}}\n").unwrap();
	} else {
		// Write in which order to play patterns
		write!(writer, "song_pattern_list:\n").unwrap();
		for i in 0..module.length {
			let position = module.positions.data[i as usize];
			write!(writer, "\tdefw song_pattern_{}\n", position).unwrap();
		}
		// Terminate list
		write!(writer, "\tdefw 0\n").unwrap();
		write!(writer, "\n").unwrap();

		// Write pattern data
		let mut pattern_no = 0;
		for pattern in module.patterns {
			write!(writer,"song_pattern_{}:\n", pattern_no).unwrap();
			pattern_no += 1;
			for row in pattern.rows {
				let mut number = -1;
				for channel in row.channels {
					if channel.sample_number > 0 {
						number = channel.sample_number as i8 - 1;
						break;
					}
				}
				write!(writer,"\tdefb {}\n", number).unwrap();
			}
			write!(writer,"\n").unwrap();
		}
	}

	println!("Done!");
}
<commit_msg>One octave lower<commit_after>use std::fs::File;
use std::io::BufWriter;
use std::io::Write;
use std::io::BufReader;
use std::io::Read;

extern crate modfile;
use modfile::ptmf;

extern crate rustc_serialize;
extern crate docopt;
use docopt::Docopt;

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

static USAGE: &'static str = "
mod2abc.

Usage:
    mod2abc (-h | --help)
    mod2abc (-V | --version)
    mod2abc --in=<filename> --out=<filename> [--format-jbe]

Options:
    -V, --version         Show version info.
    -h, --help            Show this text.
	--in=<filename>       Name of inputfile
	--out=<filename>      Name of outputfile
	--format-jbe          Use format for jbe replay
";

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

	flag_in: String,
	flag_out: String,
	flag_format_jbe: bool
}

fn note_from_period(period: u16) -> String {
	// Find the position in PERIODS with the
	// smallest difference
	let mut found:i32 = -1;
	let mut min_diff = 65536;
	let key = period as i32;
	for i in 0..ptmf::PERIODS.len() {
		let diff = (key as i32 - ptmf::PERIODS[i] as i32).abs();
		if diff < min_diff {
			min_diff = diff;
			found = i as i32;
		}
	}

	let note = if found == -1 {
		println!("Failed to find note name");
		String::new()
	} else {
		let octave = found / 12;
		let name = ptmf::NOTE_NAMES[(found % 12) as usize];
		if octave == 1 {
			// Lower case
			name.to_lowercase()
		} else if octave == 2 {
			// Upper case
			name.to_uppercase()
		} else {
			format!("O{}{}",octave,name)
		}
	};

	note
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
//    println!("{:?}", args);

	if args.flag_version {
		println!("Version: {}", VERSION);
		return;
	}

	if args.flag_in == "" {
		println!("No inputfile specificed");
		return
	}

	if args.flag_out == "" {
		println!("No outputfile specificed");
		return
	}

	let ref input_filename = args.flag_in;
	let file = match File::open(input_filename) {
		Ok(file) => file,
		Err(e) => {
			println!("Failed to open file: '{}' Error: '{}'", input_filename, e);
			return
		}
	};

	let read_fn:fn (&mut Read) -> Result<ptmf::PTModule, ptmf::PTMFError> = ptmf::read_mod;

	let mut reader = BufReader::new(&file);
	let module = match read_fn(&mut reader) {
		Ok(module) => module,
		Err(e) => {
			println!("Failed to parse file: '{}' Error: '{:?}'", input_filename, e);
			return;
		}
	};

	let ref output_filename = args.flag_out;
	let file = match File::create(&output_filename) {
		Ok(file) => file,
		Err(e) => {
			println!("Failed to open file: '{}' Error: '{:?}'", output_filename, e);
			return
		}
	};

	let mut writer = BufWriter::new(&file);

	if args.flag_format_jbe {
		// Write in which order to play patterns
		write!(writer, "song\n").unwrap();
		write!(writer, "{{\n\t").unwrap();
		for i in 0..module.length {
			let position = module.positions.data[i as usize];
			if i == 0 {
				write!(writer, "{}", position).unwrap();
			} else {
				write!(writer, ",{}", position).unwrap();
			}
		}
		write!(writer, "\n}}\n").unwrap();

		// Write patterns
		write!(writer, "patterns\n").unwrap();
		write!(writer, "{{\n").unwrap();
		let mut pattern_no = 0;
		for pattern in module.patterns {
			write!(writer,"\t{}:", pattern_no).unwrap();
			// Loop through the pattern three times
			// 0 = just sample number
			// 1,2 = just pitch
			let mut row_no = 0;
			for row in &pattern.rows {
				let ref channel = row.channels[0];
				if row_no != 0 {
					write!(writer,",").unwrap();
				}
				if channel.sample_number > 0 {
					let number = channel.sample_number as i8;
					write!(writer,"S{}", number).unwrap();
				}
				row_no += 1;
			}
			write!(writer,"\n").unwrap();

			write!(writer,"\t{}:", pattern_no).unwrap();
			row_no = 0;
			for row in &pattern.rows {
				let ref channel = row.channels[1];
				if row_no != 0 {
					write!(writer,",").unwrap();
				}
				if channel.period > 0 {
					let note = note_from_period(channel.period);
					write!(writer,"{}", note).unwrap();
				}
				row_no += 1;
			}
			write!(writer,"\n").unwrap();

			write!(writer,"\t{}:", pattern_no).unwrap();
			row_no = 0;
			for row in &pattern.rows {
				let ref channel = row.channels[2];
				if row_no != 0 {
					write!(writer,",").unwrap();
				}
				if channel.period > 0 {
					let note = note_from_period(channel.period);
					write!(writer,"{}", note).unwrap();
				}
				row_no += 1;
			}
			write!(writer,"\n").unwrap();

			write!(writer,"\n").unwrap();
			pattern_no += 1;
		}
		write!(writer, "}}\n").unwrap();
	} else {
		// Write in which order to play patterns
		write!(writer, "song_pattern_list:\n").unwrap();
		for i in 0..module.length {
			let position = module.positions.data[i as usize];
			write!(writer, "\tdefw song_pattern_{}\n", position).unwrap();
		}
		// Terminate list
		write!(writer, "\tdefw 0\n").unwrap();
		write!(writer, "\n").unwrap();

		// Write pattern data
		let mut pattern_no = 0;
		for pattern in module.patterns {
			write!(writer,"song_pattern_{}:\n", pattern_no).unwrap();
			pattern_no += 1;
			for row in pattern.rows {
				let mut number = -1;
				for channel in row.channels {
					if channel.sample_number > 0 {
						number = channel.sample_number as i8 - 1;
						break;
					}
				}
				write!(writer,"\tdefb {}\n", number).unwrap();
			}
			write!(writer,"\n").unwrap();
		}
	}

	println!("Done!");
}
<|endoftext|>


<commit_before>#![feature(advanced_slice_patterns, slice_patterns)]

extern crate git_together;

use std::env;
use std::process::Command;

use git_together::GitTogether;
use git_together::author::AuthorParser;
use git_together::errors::*;
use git_together::git::{Config, GitConfig};

fn main() {
  run(|| {
    let all_args: Vec<_> = env::args().skip(1).collect();
    let args: Vec<&str> = all_args.iter().map(String::as_ref).collect();

    match *args.as_slice() {
      ["with"] => {
        let mut gt = git_together()?;

        gt.set_active(&[])?;
        let authors = gt.all_authors()?;
        let mut sorted: Vec<_> = authors.iter().collect();
        sorted.sort_by(|a, b| a.0.cmp(b.0));

        for (initials, author) in sorted {
          println!("{}: {}", initials, author);
        }
      }
      ["with", ref inits..] => {
        let mut gt = git_together()?;

        let authors = gt.set_active(inits)?;
        for author in authors {
          println!("{}", author);
        }
      }
      [sub_cmd, ref rest..] if ["commit", "merge", "revert"]
        .contains(&sub_cmd) => {
        let mut gt = git_together()?;

        if sub_cmd == "merge" {
          env::set_var("GIT_TOGETHER_NO_SIGNOFF", "1");
        }

        let mut cmd = Command::new("git");
        let cmd = cmd.arg(sub_cmd).args(rest);

        let signoff = gt.signoff(cmd)?;
        let status = signoff.status()
          .chain_err(|| "failed to execute process")?;
        if status.success() {
          gt.rotate_active()?;
        }
      }
      [ref args..] => {
        Command::new("git").args(args)
          .status()
          .chain_err(|| "failed to execute process")?;
      }
    };

    Ok(())
  })
}

fn git_together() -> Result<GitTogether<GitConfig>> {
  let mut config = GitConfig::new("git-together")?;
  config.auto_include();

  let domain = config.get("domain")?;
  let author_parser = AuthorParser { domain: domain };

  Ok(GitTogether::new(config, author_parser))
}

fn run<F>(f: F)
  where F: Fn() -> Result<()>
{
  if let Err(error) = f() {
    for error in error.iter() {
      println!("{}", error);
    }
    std::process::exit(1);
  }
}
<commit_msg>add version info<commit_after>#![feature(advanced_slice_patterns, slice_patterns)]

extern crate git_together;

use std::env;
use std::process::Command;

use git_together::GitTogether;
use git_together::author::AuthorParser;
use git_together::errors::*;
use git_together::git::{Config, GitConfig};

fn main() {
  run(|| {
    let all_args: Vec<_> = env::args().skip(1).collect();
    let args: Vec<&str> = all_args.iter().map(String::as_ref).collect();

    match *args.as_slice() {
      ["with"] => {
        println!("{} {}",
                 option_env!("CARGO_PKG_NAME").unwrap_or("git-together"),
                 option_env!("CARGO_PKG_VERSION").unwrap_or("unknown version"));

        let mut gt = git_together()?;

        gt.set_active(&[])?;
        let authors = gt.all_authors()?;
        let mut sorted: Vec<_> = authors.iter().collect();
        sorted.sort_by(|a, b| a.0.cmp(b.0));

        for (initials, author) in sorted {
          println!("{}: {}", initials, author);
        }
      }
      ["with", ref inits..] => {
        let mut gt = git_together()?;

        let authors = gt.set_active(inits)?;
        for author in authors {
          println!("{}", author);
        }
      }
      [sub_cmd, ref rest..] if ["commit", "merge", "revert"]
        .contains(&sub_cmd) => {
        let mut gt = git_together()?;

        if sub_cmd == "merge" {
          env::set_var("GIT_TOGETHER_NO_SIGNOFF", "1");
        }

        let mut cmd = Command::new("git");
        let cmd = cmd.arg(sub_cmd).args(rest);

        let signoff = gt.signoff(cmd)?;
        let status = signoff.status()
          .chain_err(|| "failed to execute process")?;
        if status.success() {
          gt.rotate_active()?;
        }
      }
      [ref args..] => {
        Command::new("git").args(args)
          .status()
          .chain_err(|| "failed to execute process")?;
      }
    };

    Ok(())
  })
}

fn git_together() -> Result<GitTogether<GitConfig>> {
  let mut config = GitConfig::new("git-together")?;
  config.auto_include();

  let domain = config.get("domain")?;
  let author_parser = AuthorParser { domain: domain };

  Ok(GitTogether::new(config, author_parser))
}

fn run<F>(f: F)
  where F: Fn() -> Result<()>
{
  if let Err(error) = f() {
    for error in error.iter() {
      println!("{}", error);
    }
    std::process::exit(1);
  }
}
<|endoftext|>


<commit_before>extern crate hyper;

use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};

fn handle_client(mut stream: TcpStream) {
    const SIZE: usize = 1024;
    let mut buf: Vec<u8> = Vec::with_capacity(SIZE);
    match stream.read(buf.as_mut_slice()) {
        Err(e) => { println!("Error reading request: {}", e); }
        Ok(_) => {
            match std::str::from_utf8(buf.as_mut_slice()) {
                Err(e) => { println!("Error making buffer: {}", e); }
                Ok(req) => { println!("Here is what I got: {}", req); }
            }
        }
    }

    let resp = b"HTTP/1.1 200 OK\r\nContent-Type: text/html; Connection: close;\r\n\r\nHello!\n";
    match stream.write(resp) {
        Err(e) => { println!("Error writing response: {}", e); }
        Ok(_) => {}
    }
}

fn main() {
    let listener = TcpListener::bind("127.0.0.1:42007");

    let mut acceptor = listener.listen();

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("Error in stream: {}", e); }
            Ok(stream) => { handle_client(stream) }
        }
    }

    drop(acceptor);
}
<commit_msg>updated to use hyper this time<commit_after>#![allow(unstable)]
extern crate hyper;

#[macro_use] extern crate log;

use std::io::net::ip::Ipv4Addr;

use hyper::Get;
use hyper::header::ContentLength;
use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri::AbsolutePath;

macro_rules! try_return(
    ($e:expr) => {{
        match $e {
            Ok(v) => v,
            Err(e) => { error!("Error: {}", e); return; }
        }
    }}
);

fn default(req: Request, mut res: Response) {
    match req.uri {
        AbsolutePath(ref path) => match (&req.method, path.as_slice()) {
            (&Get, _) => {
                let out = b"Test\n";
                println!("Path is: {}", path.as_slice());

                res.headers_mut().set(ContentLength(out.len() as u64));
                let mut res = try_return!(res.start());
                try_return!(res.write(out));
                try_return!(res.end());
                return;
            },
            _ => {
                *res.status_mut() = hyper::NotFound;
                try_return!(res.start().and_then(|res| res.end()));
                return;
            }
        },
        _ => {
            try_return!(res.start().and_then(|res| res.end()));
            return;
        }
    };
}

fn main() {
    let server = Server::http(Ipv4Addr(127, 0, 0, 1), 42007);
    let mut listener = server.listen(default).unwrap();
    println!("Listening on port 42007...");
    listener.await();
}
<|endoftext|>


<commit_before>#![feature(libc)]
extern crate libc;
use std::ffi;

extern crate rustwlc;

use rustwlc::types;
use rustwlc::types::*;
//use rustwlc::types::LibinputDevice;
use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::interface::*;
use rustwlc::input::pointer;
use rustwlc::input::keyboard;
/*
struct CompositorAction {
    view: WlcView,
    grab: Point,
    edges: u32
}

static mut compositor: CompositorAction = CompositorAction {
    view: WlcView(0),
    grab: Point{ x: 0, y: 0},
    edges: 0
};
*/
fn main() {
    let interface: WlcInterface = WlcInterface {
        output: OutputInterface {
            created: output_created,
            destroyed: output_destroyed,
            focus: output_focus,
            resolution: output_resolution,

            render: OutputRenderInterface {
                pre: output_render_pre,
                post: output_render_post
            }
        },
        view: ViewInterface {
            created: view_created,
            destroyed: view_destroyed,
            focus: view_focus,
            move_to_output: view_move_to_output,
            request: RequestInterface {
                geometry: view_request_geometry,
                state: view_request_state,
                move_: view_request_move,
                resize: view_request_resize,
                render: ViewRenderInterface {
                    pre: view_request_render_pre,
                    post: view_request_render_post
                }
            }
        },
        keyboard: KeyboardInterface {
            key: keyboard_key
        },
        pointer: PointerInterface {
            button: pointer_button,
            scroll: pointer_scroll,
            motion: pointer_motion
        },
        touch: TouchInterface {
            touch: touch_touch
        },
        compositor: CompositorInterface {
            ready: compositor_ready
        },
        input: InputInterface {
            created: input_created,
            destroyed: input_destroyed
        }
    };
    // Interfaces don't derive debug
    //println!("Created interface {:?}", interface);
    rustwlc::log_set_handler(log_callback);

    if !rustwlc::init(interface) {
        panic!("Unable to initialize wlc!");
    }
    rustwlc::run_wlc();
}

extern fn log_callback(log_type: LogType, text: *const libc::c_char) {
    let string_text = rustwlc::pointer_to_string(text);
    println!("Wlc Log: {}", string_text);
}

// Important rendering functions copied from wlc/example/example.c

fn start_interactive_action(view: WlcView, origin: Point) -> bool {
    true
}

fn stop_interactive_action() {

}

fn start_interactive_move(view: WlcView, origin: Point) {

}

fn start_interactive_resize(view: WlcView, edges: u32, origin: Point) {

}

fn get_topmost_view(output: WlcOutput, offset: Size) {

}

/// From example.c:
/// very simple layout function
/// you probably don't want to layout certain type of windows in wm
fn render_output(output: WlcOutput) {
    let resolution = output.get_resolution();
    //let views = output.get_views();
}

// Hook up basic callbacks

extern fn output_created(output: WlcOutput) -> bool {
    println!("output_created");
    return true;
}

extern fn output_destroyed(output: WlcOutput) {
    println!("output_destroyed");
}

extern fn output_focus(output: WlcOutput, focused: bool) {
    println!("output_focus: {}", focused);
}

extern fn output_resolution(output: WlcOutput, old_size: Size, new_size: Size) {
    println!("output_resolution: {:?} to {:?}", old_size, new_size)
}

extern fn output_render_pre(output: WlcOutput) {
    //println!("output_render_pre");
}

extern fn output_render_post(output: WlcOutput) {
    //println!("output_render_post");
}

extern fn view_created(view: WlcView) -> bool {
    println!("view_created");
    view.bring_to_front();
    view.focus();
    render_output(view.get_output());
    true
}

extern fn view_destroyed(view: WlcView) {
    println!("view_destroyed");
    //let next_up =
}

extern fn view_focus(current: WlcView, focused: bool) {
    println!("view_focus: {}", focused);
    //view.set_state()
}

extern fn view_move_to_output(current: WlcView, q1: WlcView, q2: WlcView) {
    println!("view_move_to_output");
}

extern fn view_request_geometry(view: WlcView, geometry: Geometry) {
    println!("view_request_geometry: call wlc_view_set_geometry({:?})", geometry);
}

extern fn view_request_state(view: WlcView, state: ViewState, handled: bool) {
    println!("view_request_state: call wlc_view_set_state({:?})", state);
}

extern fn view_request_move(view: WlcView, dest: Point) {
    println!("view_request_move: to {}, start interactive mode.", dest);
}

extern fn view_request_resize(view: WlcView, edge: ResizeEdge, location: Point) {
    println!("view_request_resize: size {:?}, to {}, start interactive mode.",
             edge, location);
}

extern fn view_request_render_pre(view: WlcView) {
    //println!("view_request_render_pre");
}

extern fn view_request_render_post(view: WlcView) {
    //println!("view_request_render_post");
}

extern fn keyboard_key(view: WlcView, time: u32, mods: KeyboardModifiers,
                       key: u32, state: KeyState) -> bool {
    use std::process::{Command};
    println!("keyboard_key: time {}, mods {:?}, key {:?}, state {:?}",
             time, mods, key, state);
    println!("Preparing to open the terminal...");
    rustwlc::exec("weston-terminal".to_string(), vec!["weston-terminal".to_string()]);
    // We are definitely able to open programs, they can definitely launch in the host X11 server.
    //rustwlc::exec("emacs".to_string(), vec!["emacs".to_string()]);
    //let output = std::process::Command::new("weston-terminal").output()
    //.unwrap_or_else(|e| { println!("Could not unwrap output!"); panic!("aaaa") });
    let mut child = Command::new("/bin/weston-terminal").spawn()
        .unwrap_or_else(|e| { println!("Error spawning child: {}", e); panic!("1") });

    //let ecode = child.wait().unwrap_or_else(|e| println!("Error unwrapping child"));
    //println!("Output: {}", String::from_utf8(output.stdout).unwrap_or("nope".to_string()));

    false
}

extern fn pointer_button(view: WlcView, button: libc::c_uint, mods: KeyboardModifiers,
                  key: u32, state: ButtonState, point: Point) -> bool {
    println!("pointer_button: key {}, point {}", key, point);

    if state == ButtonState::Pressed {
        view.focus();
    }
    false
}

extern fn pointer_scroll(view: WlcView, button: u32, mods: KeyboardModifiers,
                  axis: ScrollAxis, heights: [u64; 2]) -> bool {
    println!("pointer_scroll");
    false
}

extern fn pointer_motion(view: WlcView, time: u32, point: Point) {
    //println!("Pointer moved {} to {}", time, point);
    // TODO wlc_pointer_set_position
    pointer::set_position(point);
}

extern fn touch_touch(view: WlcView, time: libc::c_uint, mods: KeyboardModifiers,
               touch: TouchType, key: i32, point: Point) -> bool {
    false
}

extern fn compositor_ready() {
    println!("Preparing compositor!");
}

extern fn input_created(device: LibinputDevice) -> bool {
    println!("input_created");
    false
}

extern fn input_destroyed(device: LibinputDevice) {
    println!("input_destroyed");
}
<commit_msg>Beginning crunch on making views actually render<commit_after>#![feature(libc)]
extern crate libc;
use std::ffi;

extern crate rustwlc;

use rustwlc::types;
use rustwlc::types::*;
//use rustwlc::types::LibinputDevice;
use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::interface::*;
use rustwlc::input::pointer;
use rustwlc::input::keyboard;
/*
struct CompositorAction {
    view: WlcView,
    grab: Point,
    edges: u32
}

static mut compositor: CompositorAction = CompositorAction {
    view: WlcView(0),
    grab: Point{ x: 0, y: 0},
    edges: 0
};
*/
fn main() {
    let interface: WlcInterface = WlcInterface {
        output: OutputInterface {
            created: output_created,
            destroyed: output_destroyed,
            focus: output_focus,
            resolution: output_resolution,

            render: OutputRenderInterface {
                pre: output_render_pre,
                post: output_render_post
            }
        },
        view: ViewInterface {
            created: view_created,
            destroyed: view_destroyed,
            focus: view_focus,
            move_to_output: view_move_to_output,
            request: RequestInterface {
                geometry: view_request_geometry,
                state: view_request_state,
                move_: view_request_move,
                resize: view_request_resize,
                render: ViewRenderInterface {
                    pre: view_request_render_pre,
                    post: view_request_render_post
                }
            }
        },
        keyboard: KeyboardInterface {
            key: keyboard_key
        },
        pointer: PointerInterface {
            button: pointer_button,
            scroll: pointer_scroll,
            motion: pointer_motion
        },
        touch: TouchInterface {
            touch: touch_touch
        },
        compositor: CompositorInterface {
            ready: compositor_ready
        },
        input: InputInterface {
            created: input_created,
            destroyed: input_destroyed
        }
    };
    // Interfaces don't derive debug
    //println!("Created interface {:?}", interface);
    rustwlc::log_set_handler(log_callback);

    if !rustwlc::init(interface) {
        panic!("Unable to initialize wlc!");
    }
    rustwlc::run_wlc();
}

extern fn log_callback(log_type: LogType, text: *const libc::c_char) {
    let string_text = rustwlc::pointer_to_string(text);
    println!("Wlc Log: {}", string_text);
}

// Important rendering functions copied from wlc/example/example.c

fn start_interactive_action(view: WlcView, origin: Point) -> bool {
    true
}

fn stop_interactive_action() {

}

fn start_interactive_move(view: WlcView, origin: Point) {

}

fn start_interactive_resize(view: WlcView, edges: u32, origin: Point) {

}

fn get_topmost_view(output: WlcOutput, offset: Size) {

}

/// From example.c:
/// very simple layout function
/// you probably don't want to layout certain type of windows in wm
fn render_output(output: WlcOutput) {
    use std::cmp;
    let resolution = output.get_resolution();
    let views = output.get_views();

    if views.len() == 0 { println!("Didn't find any views to render :/"); }

    for view in views {
        view.set_geometry(0,
                          Geometry {
                              size: Size {
                                  w: resolution.w as u32,
                                  h: resolution.h as u32
                              },
                              origin: Point {
                                  x: resolution.w as i32,
                                  y: resolution.h as i32
                              }
                          });
    }

    /*
    let mut toggle = false;
    let mut y = 0u32;
//    use std::cmp;

    let w: u32 = resolution.w as u32 / 2u32;
    let h: u32 = resolution.h as u32 / cmp::max((1u32 + views.len() as u32) / 2u32, 1);

    for view in views {
        let g = Geometry {
            size: Size {
                w: if toggle { w } else { 0 },
                h: y
            },
            origin: Point {
                x: if !toggle { resolution.w as i32 } else { w as i32 },
                y: h as i32
            }
        };
        view.set_geometry(0, g);
        toggle = !toggle;
        y = y + if !toggle { h } else { 0 };
    }*/
}

// Hook up basic callbacks

extern fn output_created(output: WlcOutput) -> bool {
    println!("output_created");
    return true;
}

extern fn output_destroyed(output: WlcOutput) {
    println!("output_destroyed");
}

extern fn output_focus(output: WlcOutput, focused: bool) {
    println!("output_focus: {}", focused);
}

extern fn output_resolution(output: WlcOutput, old_size: Size, new_size: Size) {
    println!("output_resolution: {:?} to {:?}", old_size, new_size)
}

extern fn output_render_pre(output: WlcOutput) {
    //println!("output_render_pre");
}

extern fn output_render_post(output: WlcOutput) {
    //println!("output_render_post");
}

extern fn view_created(view: WlcView) -> bool {
    println!("view_created: {:?}", view);
    let output = view.get_output();
    println!("view_created: it's on output {:?}", output);
    view.set_mask(output.get_mask());
    view.bring_to_front();
    view.focus();
    render_output(output);
    true
}

extern fn view_destroyed(view: WlcView) {
    println!("view_destroyed: {:?}", view);
    render_output(view.get_output());
}

extern fn view_focus(current: WlcView, focused: bool) {
    println!("view_focus: {:?} {}", current, focused);
    current.set_state(ViewState::Activated, focused);
}

extern fn view_move_to_output(current: WlcView, q1: WlcView, q2: WlcView) {
    println!("view_move_to_output: {:?}, {:?}, {:?}", current, q1, q2);
}

extern fn view_request_geometry(view: WlcView, geometry: Geometry) {
    println!("view_request_geometry: {:?} wants {:?}", view, geometry);
    view.set_geometry(0, geometry);
    render_output(view.get_output());
}

extern fn view_request_state(view: WlcView, state: ViewState, handled: bool) {
    println!("view_request_state: call wlc_view_set_state({:?})", state);
    view.set_state(state, handled);
}

extern fn view_request_move(view: WlcView, dest: Point) {
    println!("view_request_move: to {}, start interactive mode.", dest);
}

extern fn view_request_resize(view: WlcView, edge: ResizeEdge, location: Point) {
    println!("view_request_resize: size {:?}, to {}, start interactive mode.",
             edge, location);
}

extern fn view_request_render_pre(view: WlcView) {
    //println!("view_request_render_pre");
}

extern fn view_request_render_post(view: WlcView) {
    //println!("view_request_render_post");
}

extern fn keyboard_key(view: WlcView, time: u32, mods: KeyboardModifiers,
                       key: u32, state: KeyState) -> bool {
    use std::process::{Command};
    println!("keyboard_key: time {}, mods {:?}, key {:?}, state {:?}",
             time, mods, key, state);
    if state == KeyState::Pressed { return false; }
    println!("Preparing to open the terminal...");
    rustwlc::exec("weston-terminal".to_string(), vec!["weston-terminal".to_string()]);
    // We are definitely able to open programs, they can definitely launch in the host X11 server.
    //rustwlc::exec("emacs".to_string(), vec!["emacs".to_string()]);
    //let output = std::process::Command::new("weston-terminal").output()
    //.unwrap_or_else(|e| { println!("Could not unwrap output!"); panic!("aaaa") });
    let mut child = Command::new("/bin/weston-terminal").spawn()
        .unwrap_or_else(|e| { println!("Error spawning child: {}", e); panic!("1") });

    //let ecode = child.wait().unwrap_or_else(|e| println!("Error unwrapping child"));
    //println!("Output: {}", String::from_utf8(output.stdout).unwrap_or("nope".to_string()));

    false
}

extern fn pointer_button(view: WlcView, button: libc::c_uint, mods: KeyboardModifiers,
                  key: u32, state: ButtonState, point: Point) -> bool {
    println!("pointer_button: key {}, point {}", key, point);

    if state == ButtonState::Pressed {
        view.focus();
    }
    false
}

extern fn pointer_scroll(view: WlcView, button: u32, mods: KeyboardModifiers,
                  axis: ScrollAxis, heights: [u64; 2]) -> bool {
    println!("pointer_scroll");
    false
}

extern fn pointer_motion(view: WlcView, time: u32, point: Point) {
    //println!("Pointer moved {} to {}", time, point);
    // TODO wlc_pointer_set_position
    pointer::set_position(point);
}

extern fn touch_touch(view: WlcView, time: libc::c_uint, mods: KeyboardModifiers,
               touch: TouchType, key: i32, point: Point) -> bool {
    false
}

extern fn compositor_ready() {
    println!("Preparing compositor!");
}

extern fn input_created(device: LibinputDevice) -> bool {
    println!("input_created");
    false
}

extern fn input_destroyed(device: LibinputDevice) {
    println!("input_destroyed");
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate ncurses;

use std::io::{stdin, Read, BufRead, BufReader};
use std::error::Error;
use std::sync::{Arc, Mutex};
use std::thread;
use std::process::{Command, Stdio, exit};
use std::char;
use std::mem;

use ncurses::*;

//==============================================================================

struct FZF {
    query: String,
}

//==============================================================================
enum MatcherEvent{
    QUERY_CHANG,
    SELECT,
}

struct Matcher {
    query: String,
    mutex_items: Arc<Mutex<Vec<String>>>,
    matches: Vec<String>,
    display: Display,
}

impl Matcher {
    pub fn new(mtx_items: Arc<Mutex<Vec<String>>>) -> Self {
        Matcher {
            query: "my query".to_owned(),
            mutex_items: mtx_items,
            matches: vec!["one".to_owned(), "two".to_owned()],
            display: Display::new(),
        }
    }

    pub fn display_items(&mut self) {
        let mut items = self.mutex_items.lock().unwrap();
        let maxc = self.display.max_x - 3;
        self.display.prepare_print_line();
        for item in (*items).iter() {
            self.display.print_line(item);
        }
    }

    pub fn display_info(&self) {
        // XX/YY file(s)
        self.display.print_info(format!("  {}/{} file(s)", 10, 20).as_ref());
    }

    pub fn run(&mut self) {

    }
}

//==============================================================================
struct Display {
    max_y: i32,
    max_x: i32,
}

impl Display {
    pub fn new() -> Self {
        let mut max_y = 0;
        let mut max_x = 0;
        getmaxyx(stdscr, &mut max_y, &mut max_x);

        Display {
            max_y: max_y,
            max_x: max_x,
        }
    }

    pub fn print_info(& self, msg: &str) {
        // XX/YY file(s)
        mv(self.max_y-2, 0);
        clrtoeol();
        addstr(msg);
    }

    pub fn print_query(&self, query: &str, cursor: i32) {
        // > query
        mv(self.max_y-1, 0);
        clrtoeol();
        printw("> ");
        printw(query);
        mv(self.max_y-1, cursor+2);
    }

    pub fn prepare_print_line(&self) {
        mv(self.max_y-2, 2);
    }

    pub fn print_line(&self, line: &str) {
        let y = getcury(stdscr);
        mv(y, 2);
        addstr(line);
        mv(y-1, 2);
    }

    pub fn refresh(&self) {
        refresh();
    }
}

//==============================================================================
// Queryer: fetch the query string

#[derive(Debug)]
struct Queryer {
    query: String,
    pos: u32, // point to the last character of the query string
}

impl Queryer {
    pub fn new() -> Self {
        Queryer {
            query: String::new(),
            pos: 0,
        }
    }

    fn add_char (&mut self, ch: char) {
        let orig = mem::replace(&mut self.query, String::new());
        self.query.push_str(orig.chars().take(self.pos as usize).collect::<String>().as_ref());
        self.query.push(ch);
        self.query.push_str(orig.chars().skip(self.pos as usize).collect::<String>().as_ref());
        self.pos += 1;
    }

    fn delete_char(&mut self) {
        if self.pos == 0 {
            return;
        }

        let orig = mem::replace(&mut self.query, String::new());
        self.query.push_str(orig.chars().take((self.pos-1) as usize).collect::<String>().as_ref());
        self.query.push_str(orig.chars().skip(self.pos as usize).collect::<String>().as_ref());
        self.pos -= 1;
    }

    // fetch input from curses and turn it into query.
    fn handle_char(&mut self) {
        let ch = wget_wch(stdscr);

        let orig_query = self.query.clone();

        match ch {
            Some(WchResult::KeyCode(_)) => {
                // will later handle readline-like shortcuts
            }

            Some(WchResult::Char(c)) => {
                /* Enable attributes and output message. */
                let ch = char::from_u32(c as u32).expect("Invalid char");
                match ch {
                    '\x7F' => { self.delete_char(); } // backspace
                    ch => { self.add_char(ch); } // other characters
                }
            }

            None => { }
        }
    }
}

//==============================================================================
// Reader: fetch a list of lines from stdin or command output

const READER_LINES_CACHED: usize = 100;

// invoke find comand.
fn get_command_output() -> Result<Box<BufRead>, Box<Error>> {
    let command = try!(Command::new("ls")
                       .arg(".")
                       .stdout(Stdio::piped())
                       .stderr(Stdio::null())
                       .spawn());
    let stdout = try!(command.stdout.ok_or("command output: unwrap failed".to_owned()));
    Ok(Box::new(BufReader::new(stdout)))
}

struct Reader {
    lines: Vec<String>,
    mutex_output: Arc<Mutex<Vec<String>>>,
}

impl Reader {
    pub fn new(mtx: Arc<Mutex<Vec<String>>>) -> Self {
        Reader {
            lines: vec![],
            mutex_output: mtx,
        }
    }

    fn update_output(&mut self) {
        let mut items = self.mutex_output.lock().unwrap();
        (*items).extend(mem::replace(&mut self.lines, vec![]));
    }

    fn run(&mut self) {
        // check if the input is TTY
        let istty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;

        let mut read;
        if istty {
            read = get_command_output().expect("command not found: find");
        } else {
            read = Box::new(BufReader::new(stdin()))
        };

        loop {
            let mut input = String::new();
            match read.read_line(&mut input) {
                Ok(n) => {
                    if n <= 0 { break; }

                    if input.ends_with("\n") {
                        input.pop();
                        if input.ends_with("\r") {
                            input.pop();
                        }
                    }

                    self.lines.push(input);
                    if self.lines.len() >= READER_LINES_CACHED {
                        self.update_output();
                    }

                }
                Err(_err) => { break; }
            }
        }
        self.update_output();
    }
}

//==============================================================================

fn main() {
    // initialize ncurses
    let local_conf = LcCategory::all;
    setlocale(local_conf, "en_US.UTF-8"); // for showing wide characters
    initscr();
    raw();
    keypad(stdscr, true);
    noecho();

    // initialize ncurses screen
    let mtx_item = Arc::new(Mutex::new(vec![]));

    // reader
    let reader_mtx_item = mtx_item.clone();
    let mut reader = Reader::new(reader_mtx_item);
    let th_reader = thread::spawn(move || reader.run());

    let mut matcher = Matcher::new(mtx_item);
    loop {
        matcher.display_items();
        matcher.display.refresh();
        getch();
    }

    //let disp = Display::new();
    //disp.init();
    //disp.print_info(&matcher);
    //disp.print_query(&matcher);
    //disp.refresh();

    //let mut queryer = Queryer::new();

    //loop {
        //queryer.handle_char();
        //addstr(&queryer.query);
        //addstr(format!("pos: {}", queryer.pos).as_ref());
        //addch('\n' as u64);
        //refresh();
    //}

    // displayer
    //let displayer_mtx_item = mtx_item.clone();
    //let displayer = thread::spawn(move || {
        //loop {
            //let mut items = displayer_mtx_item.lock().unwrap();
            //if (*items).len() > 0 {
                //println!("Got: {:?}", *items);
                //*items = vec![];
            //}
        //}
    //});

    //getch();
    //endwin();
    th_reader.join();
    //displayer.join();
}
<commit_msg>[main] reader/matcher communication done.<commit_after>extern crate libc;
extern crate ncurses;

mod util;

use std::io::{stdin, Read, BufRead, BufReader};
use std::error::Error;
use std::sync::{Arc, Mutex};
use std::thread;
use std::process::{Command, Stdio, exit};
use std::char;
use std::mem;
use std::sync::mpsc::{Sender, Receiver, channel};
use util::eventbox::EventBox;

use ncurses::*;

//==============================================================================

struct FZF {
    query: String,
}

//==============================================================================
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
enum Event{
    EV_READER_NEW,
    EV_READER_FIN,
    EV_MATCHER_NEW_ITEM,
    EV_MATCHER_RESET_QUERY,
    EV_MATCHER_UPDATE_PROCESS,
    EV_MATCHER_FINISHED,
}

// matcher will receive two events:
// 1. EV_MATCHER_NEW_ITEM, to reset the input strings
// 2. EV_MATCHER_RESET_QUERY, to interrupt current processing.
//
// will send two events:
// 1. EV_MATCHER_UPDATE_PROCESS, to notify the matched/total items
// 2. EV_MATCHER_FINISHED.

struct Matcher {
    rx_source: Receiver<String>, // channel to retrieve strings from reader
    tx_output: Sender<String>,   // channel to send output to
    eb_req: Arc<EventBox<Event>>,       // event box that recieve requests
    eb_notify: Arc<EventBox<Event>>,    // event box that send out notification
    items: Vec<String>,
    item_pos: usize,
    query: String,
}

impl Matcher {
    pub fn new(rx_source: Receiver<String>, tx_output: Sender<String>,
               eb_req: Arc<EventBox<Event>>, eb_notify: Arc<EventBox<Event>>) -> Self {
        Matcher{
            rx_source: rx_source,
            tx_output: tx_output,
            eb_req: eb_req,
            eb_notify: eb_notify,
            items: Vec::new(),
            item_pos: 0,
            query: String::new(),
        }
    }

    pub fn process(&mut self) {
        for string in self.items[self.item_pos..].into_iter() {
            // process the matcher
            //self.tx_output.send(string.clone());
            (*self.eb_notify).set(Event::EV_MATCHER_UPDATE_PROCESS, Box::new(0));
            self.tx_output.send(string.clone());

            self.item_pos += 1;
            if (self.item_pos % 100) == 99 && !self.eb_req.is_empty() {
                break;
            }
        }
    }

    fn read_new_item(&mut self) {
        while let Ok(string) = self.rx_source.try_recv() {
            self.items.push(string);
        }
    }

    fn reset_query(&mut self, query: &str) {
        self.query.clear();
        self.query.push_str(query);
    }

    pub fn run(&mut self) {
        loop {
            for (e, val) in (*self.eb_req).wait() {
                match e {
                    Event::EV_MATCHER_NEW_ITEM => { self.read_new_item();}
                    Event::EV_MATCHER_RESET_QUERY => {self.reset_query(*val.downcast().unwrap());}
                    _ => {}
                }
            }

            self.process()
        }
    }
}

//==============================================================================
struct Display {
    max_y: i32,
    max_x: i32,
}

impl Display {
    pub fn new() -> Self {
        let mut max_y = 0;
        let mut max_x = 0;
        getmaxyx(stdscr, &mut max_y, &mut max_x);

        Display {
            max_y: max_y,
            max_x: max_x,
        }
    }

    pub fn print_info(& self, msg: &str) {
        // XX/YY file(s)
        mv(self.max_y-2, 0);
        clrtoeol();
        addstr(msg);
    }

    pub fn print_query(&self, query: &str, cursor: i32) {
        // > query
        mv(self.max_y-1, 0);
        clrtoeol();
        printw("> ");
        printw(query);
        mv(self.max_y-1, cursor+2);
    }

    pub fn prepare_print_line(&self) {
        mv(self.max_y-2, 2);
    }

    pub fn print_line(&self, line: &str) {
        let y = getcury(stdscr);
        mv(y, 2);
        addstr(line);
        mv(y-1, 2);
    }

    pub fn refresh(&self) {
        refresh();
    }
}

//==============================================================================
// Queryer: fetch the query string

#[derive(Debug)]
struct Queryer {
    query: String,
    pos: u32, // point to the last character of the query string
}

impl Queryer {
    pub fn new() -> Self {
        Queryer {
            query: String::new(),
            pos: 0,
        }
    }

    fn add_char (&mut self, ch: char) {
        let orig = mem::replace(&mut self.query, String::new());
        self.query.push_str(orig.chars().take(self.pos as usize).collect::<String>().as_ref());
        self.query.push(ch);
        self.query.push_str(orig.chars().skip(self.pos as usize).collect::<String>().as_ref());
        self.pos += 1;
    }

    fn delete_char(&mut self) {
        if self.pos == 0 {
            return;
        }

        let orig = mem::replace(&mut self.query, String::new());
        self.query.push_str(orig.chars().take((self.pos-1) as usize).collect::<String>().as_ref());
        self.query.push_str(orig.chars().skip(self.pos as usize).collect::<String>().as_ref());
        self.pos -= 1;
    }

    // fetch input from curses and turn it into query.
    fn handle_char(&mut self) {
        let ch = wget_wch(stdscr);

        let orig_query = self.query.clone();

        match ch {
            Some(WchResult::KeyCode(_)) => {
                // will later handle readline-like shortcuts
            }

            Some(WchResult::Char(c)) => {
                /* Enable attributes and output message. */
                let ch = char::from_u32(c as u32).expect("Invalid char");
                match ch {
                    '\x7F' => { self.delete_char(); } // backspace
                    ch => { self.add_char(ch); } // other characters
                }
            }

            None => { }
        }
    }
}

//==============================================================================
// Reader: fetch a list of lines from stdin or command output

const READER_LINES_CACHED: usize = 100;

struct Reader {
    cmd: Option<&'static str>, // command to invoke
    eb: Arc<EventBox<Event>>,         // eventbox
    tx: Sender<String>,    // sender to send the string read from command output
}

impl Reader {

    pub fn new(cmd: Option<&'static str>, eb: Arc<EventBox<Event>>, tx: Sender<String>) -> Self {
        Reader{cmd: cmd, eb: eb, tx: tx}
    }

    // invoke find comand.
    fn get_command_output(&self) -> Result<Box<BufRead>, Box<Error>> {
        let command = try!(Command::new("sh")
                           .arg("-c")
                           .arg(self.cmd.unwrap_or("find ."))
                           .stdout(Stdio::piped())
                           .stderr(Stdio::null())
                           .spawn());
        let stdout = try!(command.stdout.ok_or("command output: unwrap failed".to_owned()));
        Ok(Box::new(BufReader::new(stdout)))
    }

    fn run(&mut self) {
        // check if the input is TTY
        let istty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;

        let mut read;
        if istty {
            read = self.get_command_output().expect("command not found");
        } else {
            read = Box::new(BufReader::new(stdin()))
        };

        loop {
            let mut input = String::new();
            match read.read_line(&mut input) {
                Ok(n) => {
                    if n <= 0 { break; }

                    if input.ends_with("\n") {
                        input.pop();
                        if input.ends_with("\r") {
                            input.pop();
                        }
                    }
                    self.tx.send(input);
                }
                Err(_err) => { break; }
            }
            self.eb.set(Event::EV_READER_NEW, Box::new(0));
        }
        self.eb.set(Event::EV_READER_FIN, Box::new(0));
    }
}

//==============================================================================

fn main() {
    // initialize ncurses
    let local_conf = LcCategory::all;
    setlocale(local_conf, "en_US.UTF-8"); // for showing wide characters
    initscr();
    raw();
    keypad(stdscr, true);
    noecho();

    let eb = Arc::new(EventBox::new());
    let eb_clone_reader = eb.clone();
    let eb_clone_matcher = eb.clone();
    let (tx_source, rx_source) = channel();
    let (tx_matched, rx_matched) = channel();
    let mut reader = Reader::new(Some(&"find ."), eb_clone_reader, tx_source);
    let eb_matcher = Arc::new(EventBox::new());
    let eb_matcher_clone = eb_matcher.clone();
    let mut matcher = Matcher::new(rx_source, tx_matched, eb_matcher_clone, eb_clone_matcher);

    // start running
    thread::spawn(move || {
        reader.run();
    });

    thread::spawn(move || {
        matcher.run();
    });

    let mut items = vec![];

    loop {
        for (e, val) in eb.wait() {
            match e {
                Event::EV_READER_NEW => {
                    //printw("READER_NEW!\n");
                    eb_matcher.set(Event::EV_MATCHER_NEW_ITEM, Box::new(0));
                }
                Event::EV_READER_FIN => {
                    //printw("READER_FIN\n");
                }
                Event::EV_MATCHER_UPDATE_PROCESS => {
                    printw(format!("UPDATE_PROCESS: {}\n", items.len()).as_str());
                    while let Ok(string) = rx_matched.try_recv() {
                        items.push(string);
                    }
                }
                _ => {
                    printw(format!("{}\n", e as i32).as_str());
                }
            }
        }

        // print items
        let mut y = 0;
        for string in items.iter() {
            mv(y, 0);
            printw(string);
            y += 1;
        }

        refresh();
    };

    //let disp = Display::new();
    //disp.init();
    //disp.print_info(&matcher);
    //disp.print_query(&matcher);
    //disp.refresh();

    //let mut queryer = Queryer::new();

    //loop {
        //queryer.handle_char();
        //addstr(&queryer.query);
        //addstr(format!("pos: {}", queryer.pos).as_ref());
        //addch('\n' as u64);
        //refresh();
    //}

    // displayer
    //let displayer_mtx_item = mtx_item.clone();
    //let displayer = thread::spawn(move || {
        //loop {
            //let mut items = displayer_mtx_item.lock().unwrap();
            //if (*items).len() > 0 {
                //println!("Got: {:?}", *items);
                //*items = vec![];
            //}
        //}
    //});

    //getch();
    //endwin();
    //th_reader.join();
    //displayer.join();
}
<|endoftext|>


<commit_before>extern crate gradr_backend;

#[cfg(not(test))]
fn main() {
    println!("Hello, world!");
}
<commit_msg>Testing (uncompiled)<commit_after>extern crate hyper;
extern crate gradr_backend;

use hyper::Ipv4Addr;
use gradr_backend::notification_listener::GitHubServer;

#[cfg(not(test))]
fn main() {
    let server = GitHubServer::new(Ipv4Addr(0, 0, 0, 0), 1337);
    let running_server = server.event_loop().unwrap();
    loop {
        println!("{}", running_server.get_notification());
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("hello World!");
}<commit_msg>add a variable and string interpolation<commit_after>fn main() {
	let name = "Fran";

    println!("hello {}!", name);
}<|endoftext|>


<commit_before>extern crate reqwest;
extern crate url;
extern crate chrono;
extern crate uuid;
extern crate clap;
extern crate base64;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate hmacsha1;

mod rep;

use std::io::Read;
use std::env;
use std::process::Command;
use url::Url;
use url::percent_encoding::{utf8_percent_encode, USERINFO_ENCODE_SET};
use chrono::prelude::*;
use uuid::Uuid;
use hmacsha1::hmac_sha1;
use clap::{Arg, App};

static ALIYUN_API: &'static str = "http://ecs-cn-hangzhou.aliyuncs.com";
static HTTP_GET: &'static str = "GET";

fn signature(api_params: Vec<(String, String)>) -> Vec<(String, String)> {
    /*
    Aliyun API basic params sample:
    http://ecs.aliyuncs.com/?
    TimeStamp=2016-02-23T12:46:24Z
    Format=XML
    AccessKeyId=testid
    Action=DescribeRegions
    SignatureMethod=HMAC-SHA1
    SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf
    Version=2014-05-26
    SignatureVersion=1.0
     */
    let uuid_str: &str = &Uuid::new_v4().hyphenated().to_string();
    let ts: &str = &UTC::now().format("%Y-%m-%dT%H:%M:%SZ").to_string();
    let access_key_id: &str = &env::var("ALIYUN_ACCESS_KEY_ID").unwrap();
    let mut params: Vec<(String, String)> = vec![("Timestamp", ts),
                                                 ("Format", "json"),
                                                 ("AccessKeyId", access_key_id),
                                                 ("SignatureMethod", "HMAC-SHA1"),
                                                 ("SignatureNonce", uuid_str),
                                                 ("Version", "2014-05-26"),
                                                 ("SignatureVersion", "1.0")]
            .iter()
            .map(|x| (x.0.to_string(), x.1.to_string()))
            .collect();
    params.extend(api_params);
    params.sort();
    let mut sign_params: Vec<String> = Vec::with_capacity(params.len());
    sign_params.extend(params
                           .iter()
                           .map(|param| vec![param.0.clone(), "=".to_string(), param.1.clone()].join("")));
    let string_to_sign = sign_params.join("&");
    let mut string_to_sign_percent_encoded = String::new();
    string_to_sign_percent_encoded.extend(utf8_percent_encode(&string_to_sign, USERINFO_ENCODE_SET));
    let sign_bytes = vec![HTTP_GET.to_string(),
                          "&%2F&".to_string(),
                          string_to_sign_percent_encoded
                              .replace("*", "%2A")
                              .replace("+", "%20")
                              .replace("%7E", "~")
                              .replace("&", "%26")
                              .replace("%3A", "%253A")]
            .join("")
            .into_bytes();
    let secret_bytes = vec![env::var("ALIYUN_SECRET").unwrap(), "&".to_string()]
        .join("")
        .into_bytes();
    let signed = base64::encode(&hmac_sha1(&secret_bytes, &sign_bytes));
    let mut signed_params: Vec<(String, String)> = params
        .iter()
        .map(|x| (x.0.to_string(), x.1.to_string()))
        .collect();
    signed_params.push(("Signature".to_string(), signed));
    return signed_params;
}

fn describe_regions() {
    let mut url = Url::parse(ALIYUN_API).unwrap();
    let params = signature(vec![
        ("Action".to_string(), "DescribeRegions".to_string()),
        ("RegionId".to_string(), "cn-hangzhou".to_string())]);
    url.query_pairs_mut().extend_pairs(params.into_iter());
    let client = reqwest::Client::new().unwrap();
    let mut text = String::new();
    client.get(url)
        .send()
        .unwrap()
        .read_to_string(&mut text)
        .unwrap();
    let response = serde_json::from_str::<rep::Regions>(&text).unwrap();
    for region in &response.regions {
        println!("{}\t{}", region.id, region.name);
    }
}

fn ping_ok(ip: &str) -> bool {
    let output = Command::new("ping")
        .arg(ip)
        .arg("-c 3")
        .arg("-i 1")
        .arg("-W 1")
        .output()
        .expect("failed to execute ping");
    let result = String::from_utf8_lossy(&output.stdout);
    // TODO: OS & ping version awareness
    if result.find("100% packet loss").is_some() {
        return false;
    }
    return true;
}

fn is_ssh_timeout(ip: &str) -> bool {
    let output = Command::new("ssh")
        .arg(ip)
        .arg("-o ConnectTimeout=5")
        .arg("-T")
        .output()
        .expect("failed to execute ping");

    let result = String::from_utf8_lossy(&output.stderr);
    if result.find("Connection timed out").is_some() {
        return false;
    }
    return true;
}

fn get_instances() -> Vec<rep::Instance> {
    let mut url = Url::parse(ALIYUN_API).unwrap();
    let params = signature(vec![("Action".to_string(), "DescribeInstances".to_string()),
                                // TODO: max return size is 100, need pagination if we use 100+ instances.
                                ("PageSize".to_string(), "100".to_string()),
                                ("RegionId".to_string(), "cn-beijing".to_string())]);
    url.query_pairs_mut().extend_pairs(params.into_iter());
    let client = reqwest::Client::new().unwrap();
    let mut text = String::new();
    client
        .get(url)
        .send()
        .unwrap()
        .read_to_string(&mut text)
        .unwrap();
    let response = serde_json::from_str::<rep::Instances>(&text).unwrap();
    return response.instances;
}

fn reboot_instance(instance_id: &str) {
    let mut url = Url::parse(ALIYUN_API).unwrap();
    let params = signature(vec![("Action".to_string(), "RebootInstance".to_string()),
                                ("InstanceId".to_string(), instance_id.to_string()),
                                ("ForceStop".to_string(), "true".to_string())]);
    url.query_pairs_mut().extend_pairs(params.into_iter());
    let client = reqwest::Client::new().unwrap();
    let mut response_body = String::new();
    let mut res = client.get(url).send().unwrap();
    res.read_to_string(&mut response_body).unwrap();
    if res.status() == &reqwest::StatusCode::Ok {
        println!("Reboot request to {} sended!", instance_id);
    } else {
        println!("Reboot request fail with status {:?}", res.status());
    }
}

fn reboot_unresponded_instances(check_func: &Fn(&str) -> bool) {
    let instance_info = get_instances();
    let cnt = instance_info.len();
    let mut reboot_cnt = 0;
    for instance in instance_info {
        let ip = instance.ip();
        if !check_func(ip) {
            println!("{} no ping/ssh respond, sending reboot(force) request.", ip);
            reboot_instance(&instance.id);
            reboot_cnt += 1;
        } else {
            println!("{} is OK.", ip);
        }
    }
    println!("{} instance(s) checked, {} rebooted.", cnt, reboot_cnt);
}

fn reboot_all() {
    let instance_info = get_instances();
    let cnt = instance_info.len();
    for instance in instance_info {
        reboot_instance(&instance.id);
    }
    println!("{} instance(s) reboot(force) request sended!", cnt);
}

fn reboot_single(target_ip: &str) {
    for instance in get_instances() {
        if instance.ip() == target_ip {
            reboot_instance(&instance.id);
            return;
        }
    }
    println!("Instance with IP {} not found.", target_ip);
}

fn main() {
    let matches = App::new("Aliyun ECS Controller")
        .version(env!("CARGO_PKG_VERSION"))
        .about("A cli tool for control(rebool only for now) Aliyun ECS instances.")
        .arg(Arg::with_name("COMMAND")
                 .help("command to run, choices: reboot/rebootall/list")
                 .required(true)
                 .index(1))
        .arg(Arg::with_name("checker")
                 .short("c")
                 .long("checker")
                 .value_name("checker")
                 .help("Method use to check instance availability, choices: ssh/ping")
                 .takes_value(true))
        .arg(Arg::with_name("ip")
                 .long("ip")
                 .value_name("ip")
                 .help("Specify single instance IP to reboot")
                 .takes_value(true))
        .get_matches();
    let cmd = matches.value_of("COMMAND").unwrap();
    match cmd {
        "reboot" => {
            let checker = matches.value_of("checker").unwrap_or("ssh");
            let ip = matches.value_of("ip").unwrap_or("");
            if ip == "" {
                match checker {
                    "ssh" => reboot_unresponded_instances(&is_ssh_timeout),
                    "ping" => reboot_unresponded_instances(&ping_ok),
                    _ => println!("Unknown checker."),
                }
            } else {
                reboot_single(ip);
            }
        }
        "rebootall" => {
            println!("Start reboot all nodes!");
            reboot_all()
        }
        "list" => {
            for instance in &get_instances() {
                println!("Id: {} Name: {} Public IP: {}",
                            instance.id,
                            instance.name,
                            instance.ip()
                );
            }
        }
        "regions" => {
            describe_regions();
        }
        _ => println!("Unknown command."),
    }
}
<commit_msg>Simplify json load<commit_after>extern crate reqwest;
extern crate url;
extern crate chrono;
extern crate uuid;
extern crate clap;
extern crate base64;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate hmacsha1;

mod rep;

use std::io::Read;
use std::env;
use std::process::Command;
use url::Url;
use url::percent_encoding::{utf8_percent_encode, USERINFO_ENCODE_SET};
use chrono::prelude::*;
use uuid::Uuid;
use hmacsha1::hmac_sha1;
use clap::{Arg, App};

static ALIYUN_API: &'static str = "http://ecs-cn-hangzhou.aliyuncs.com";
static HTTP_GET: &'static str = "GET";

fn signature(api_params: Vec<(String, String)>) -> Vec<(String, String)> {
    /*
    Aliyun API basic params sample:
    http://ecs.aliyuncs.com/?
    TimeStamp=2016-02-23T12:46:24Z
    Format=XML
    AccessKeyId=testid
    Action=DescribeRegions
    SignatureMethod=HMAC-SHA1
    SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf
    Version=2014-05-26
    SignatureVersion=1.0
     */
    let uuid_str: &str = &Uuid::new_v4().hyphenated().to_string();
    let ts: &str = &UTC::now().format("%Y-%m-%dT%H:%M:%SZ").to_string();
    let access_key_id: &str = &env::var("ALIYUN_ACCESS_KEY_ID").unwrap();
    let mut params: Vec<(String, String)> = vec![("Timestamp", ts),
                                                 ("Format", "json"),
                                                 ("AccessKeyId", access_key_id),
                                                 ("SignatureMethod", "HMAC-SHA1"),
                                                 ("SignatureNonce", uuid_str),
                                                 ("Version", "2014-05-26"),
                                                 ("SignatureVersion", "1.0")]
            .iter()
            .map(|x| (x.0.to_string(), x.1.to_string()))
            .collect();
    params.extend(api_params);
    params.sort();
    let mut sign_params: Vec<String> = Vec::with_capacity(params.len());
    sign_params.extend(params
                           .iter()
                           .map(|param| vec![param.0.clone(), "=".to_string(), param.1.clone()].join("")));
    let string_to_sign = sign_params.join("&");
    let mut string_to_sign_percent_encoded = String::new();
    string_to_sign_percent_encoded.extend(utf8_percent_encode(&string_to_sign, USERINFO_ENCODE_SET));
    let sign_bytes = vec![HTTP_GET.to_string(),
                          "&%2F&".to_string(),
                          string_to_sign_percent_encoded
                              .replace("*", "%2A")
                              .replace("+", "%20")
                              .replace("%7E", "~")
                              .replace("&", "%26")
                              .replace("%3A", "%253A")]
            .join("")
            .into_bytes();
    let secret_bytes = vec![env::var("ALIYUN_SECRET").unwrap(), "&".to_string()]
        .join("")
        .into_bytes();
    let signed = base64::encode(&hmac_sha1(&secret_bytes, &sign_bytes));
    let mut signed_params: Vec<(String, String)> = params
        .iter()
        .map(|x| (x.0.to_string(), x.1.to_string()))
        .collect();
    signed_params.push(("Signature".to_string(), signed));
    return signed_params;
}

fn describe_regions() {
    let mut url = Url::parse(ALIYUN_API).unwrap();
    let params = signature(vec![
        ("Action".to_string(), "DescribeRegions".to_string()),
        ("RegionId".to_string(), "cn-hangzhou".to_string())]);
    url.query_pairs_mut().extend_pairs(params.into_iter());
    let client = reqwest::Client::new().unwrap();
    let response = client.get(url)
        .send()
        .unwrap()
        .json::<rep::Regions>()
        .unwrap();
    for region in &response.regions {
        println!("{}\t{}", region.id, region.name);
    }
}

fn ping_ok(ip: &str) -> bool {
    let output = Command::new("ping")
        .arg(ip)
        .arg("-c 3")
        .arg("-i 1")
        .arg("-W 1")
        .output()
        .expect("failed to execute ping");
    let result = String::from_utf8_lossy(&output.stdout);
    // TODO: OS & ping version awareness
    if result.find("100% packet loss").is_some() {
        return false;
    }
    return true;
}

fn is_ssh_timeout(ip: &str) -> bool {
    let output = Command::new("ssh")
        .arg(ip)
        .arg("-o ConnectTimeout=5")
        .arg("-T")
        .output()
        .expect("failed to execute ping");

    let result = String::from_utf8_lossy(&output.stderr);
    if result.find("Connection timed out").is_some() {
        return false;
    }
    return true;
}

fn get_instances() -> Vec<rep::Instance> {
    let mut url = Url::parse(ALIYUN_API).unwrap();
    let params = signature(vec![("Action".to_string(), "DescribeInstances".to_string()),
                                // TODO: max return size is 100, need pagination if we use 100+ instances.
                                ("PageSize".to_string(), "100".to_string()),
                                ("RegionId".to_string(), "cn-beijing".to_string())]);
    url.query_pairs_mut().extend_pairs(params.into_iter());
    let client = reqwest::Client::new().unwrap();
    let response = client
        .get(url)
        .send()
        .unwrap()
        .json::<rep::Instances>()
        .unwrap();
    return response.instances;
}

fn reboot_instance(instance_id: &str) {
    let mut url = Url::parse(ALIYUN_API).unwrap();
    let params = signature(vec![("Action".to_string(), "RebootInstance".to_string()),
                                ("InstanceId".to_string(), instance_id.to_string()),
                                ("ForceStop".to_string(), "true".to_string())]);
    url.query_pairs_mut().extend_pairs(params.into_iter());
    let client = reqwest::Client::new().unwrap();
    let mut response_body = String::new();
    let mut res = client.get(url).send().unwrap();
    res.read_to_string(&mut response_body).unwrap();
    if res.status() == &reqwest::StatusCode::Ok {
        println!("Reboot request to {} sended!", instance_id);
    } else {
        println!("Reboot request fail with status {:?}", res.status());
    }
}

fn reboot_unresponded_instances(check_func: &Fn(&str) -> bool) {
    let instance_info = get_instances();
    let cnt = instance_info.len();
    let mut reboot_cnt = 0;
    for instance in instance_info {
        let ip = instance.ip();
        if !check_func(ip) {
            println!("{} no ping/ssh respond, sending reboot(force) request.", ip);
            reboot_instance(&instance.id);
            reboot_cnt += 1;
        } else {
            println!("{} is OK.", ip);
        }
    }
    println!("{} instance(s) checked, {} rebooted.", cnt, reboot_cnt);
}

fn reboot_all() {
    let instance_info = get_instances();
    let cnt = instance_info.len();
    for instance in instance_info {
        reboot_instance(&instance.id);
    }
    println!("{} instance(s) reboot(force) request sended!", cnt);
}

fn reboot_single(target_ip: &str) {
    for instance in get_instances() {
        if instance.ip() == target_ip {
            reboot_instance(&instance.id);
            return;
        }
    }
    println!("Instance with IP {} not found.", target_ip);
}

fn main() {
    let matches = App::new("Aliyun ECS Controller")
        .version(env!("CARGO_PKG_VERSION"))
        .about("A cli tool for control(rebool only for now) Aliyun ECS instances.")
        .arg(Arg::with_name("COMMAND")
                 .help("command to run, choices: reboot/rebootall/list")
                 .required(true)
                 .index(1))
        .arg(Arg::with_name("checker")
                 .short("c")
                 .long("checker")
                 .value_name("checker")
                 .help("Method use to check instance availability, choices: ssh/ping")
                 .takes_value(true))
        .arg(Arg::with_name("ip")
                 .long("ip")
                 .value_name("ip")
                 .help("Specify single instance IP to reboot")
                 .takes_value(true))
        .get_matches();
    let cmd = matches.value_of("COMMAND").unwrap();
    match cmd {
        "reboot" => {
            let checker = matches.value_of("checker").unwrap_or("ssh");
            let ip = matches.value_of("ip").unwrap_or("");
            if ip == "" {
                match checker {
                    "ssh" => reboot_unresponded_instances(&is_ssh_timeout),
                    "ping" => reboot_unresponded_instances(&ping_ok),
                    _ => println!("Unknown checker."),
                }
            } else {
                reboot_single(ip);
            }
        }
        "rebootall" => {
            println!("Start reboot all nodes!");
            reboot_all()
        }
        "list" => {
            for instance in &get_instances() {
                println!("Id: {} Name: {} Public IP: {}",
                            instance.id,
                            instance.name,
                            instance.ip()
                );
            }
        }
        "regions" => {
            describe_regions();
        }
        _ => println!("Unknown command."),
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Jan Likar.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate cargo;
extern crate docopt;
extern crate rustc_serialize;
extern crate cargo_clone;

use cargo::core::SourceId;
use cargo::util::{Config, CliResult};

use docopt::Docopt;

#[derive(RustcDecodable, Debug)]
pub struct Options {
    flag_verbose: bool,
    flag_quiet: bool,
    flag_color: Option<String>,

    arg_crate: Option<String>,
    flag_vers: Option<String>,

    flag_path: Option<String>,
}

pub const USAGE: &'static str = "
Clone source code of a Rust crate
Usage:
    cargo clone [options] [<crate>]

Options:
    --vers VERS               Specify a version to clone from crates.io

    -h, --help                Print this message
    -v, --verbose             Use verbose output
    -q, --quiet               Less output printed to stdout
    --color WHEN              Coloring: auto, always, never
";

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

    let config = Config::default().expect("Unable to get config");

    if let Err(e) = execute(options, config) {
        println!("{}", e.to_string())
    }
}

pub fn execute(options: Options, config: Config) -> CliResult<Option<()>> {
    try!(config.shell().set_verbosity(options.flag_verbose, options.flag_quiet));
    try!(config.shell().set_color_config(options.flag_color.as_ref().map(|s| &s[..])));

    // Make a SourceId for the default Registry (usually crates.io)
    let source_id = try!(SourceId::for_central(&config));

    try!(cargo_clone::ops::clone(&options.arg_crate, &source_id, options.flag_vers, config));

    Ok(None)
}
<commit_msg>Tidy comments and usage<commit_after>// Copyright 2015 Jan Likar.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate cargo;
extern crate docopt;
extern crate rustc_serialize;
extern crate cargo_clone;

use cargo::core::SourceId;
use cargo::util::{Config, CliResult};

use docopt::Docopt;

#[derive(RustcDecodable, Debug)]
pub struct Options {
    flag_verbose: bool,
    flag_quiet: bool,
    flag_color: Option<String>,

    arg_crate: Option<String>,
    flag_vers: Option<String>,

    flag_path: Option<String>,
}

pub const USAGE: &'static str = "
Clone source code of a Rust crate

Usage:
    cargo clone [options] [<crate>]

Options:
    --vers VERS               Specify a version to clone from crates.io
    -h, --help                Print this message
    -v, --verbose             Use verbose output
    -q, --quiet               Less output printed to stdout
    --color WHEN              Coloring: auto, always, never
";

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

    let config = Config::default().expect("Unable to get config");

    if let Err(e) = execute(options, config) {
        println!("{}", e.to_string())
    }
}

pub fn execute(options: Options, config: Config) -> CliResult<Option<()>> {
    try!(config.shell().set_verbosity(options.flag_verbose, options.flag_quiet));
    try!(config.shell().set_color_config(options.flag_color.as_ref().map(|s| &s[..])));

    // Make a SourceId for the central Registry (usually crates.io)
    let source_id = try!(SourceId::for_central(&config));

    try!(cargo_clone::ops::clone(&options.arg_crate, &source_id, options.flag_vers, config));

    Ok(None)
}
<|endoftext|>