<commit_before>extern crate yaml_rust;
extern crate regex;
extern crate rusqlite;

use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::net::TcpListener;
use std::time::Duration;
use std::sync::Arc;
use std::thread;
use std::process::exit;
use yaml_rust::YamlLoader;
use regex::bytes::RegexSetBuilder;
use rusqlite::Connection;

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

#[derive(Copy, Clone)]
struct App {
  print_ascii: bool,
  print_binary: bool,
  sql_logging: bool
}

fn to_hex(bytes: &[u8]) -> String {
  let mut count = 0;
  let mut result = String::with_capacity(67);
  let mut dotline = String::with_capacity(18);

  for byte in bytes.iter() {
    if count != 0 && count%8 == 0 {
      result.push(' ');
      if count%16 == 0 {
        dotline.push('\n');
        result.push_str(&dotline);
        result.reserve(67);
        dotline.truncate(0);
      }
      else { dotline.push(' '); }
    }
    result.push_str(&format!("{:02X} ", byte));
    if *byte > 31 && *byte < 127 { dotline.push(*byte as char) }
    else if *byte == 0 { dotline.push('-'); }
    else { dotline.push('.'); }
    count += 1;
  }
  while count%16 != 0 {
    if count%8 == 0 { result.push(' '); }
    result.push_str("   ");
    count += 1;
  }
  if dotline.len() != 0 { result.push_str(&dotline); }
  result
}

fn main() {
  let authorstring: String = str::replace(env!("CARGO_PKG_AUTHORS"), ":", "\n");
  println!("Portlurker v{}", VERSION);
  println!("{}", authorstring);
  println!("-----------------------------------------");

  let mut app = App { print_ascii: false, print_binary: false, sql_logging: false };
  let binary_matches = [
    ("SSL3.0 Record Protocol", r"^\x16\x03\x00..\x01"),
    ("TLS1.0 Record Protocol", r"^\x16\x03\x01..\x01"),
    ("TLS1.1 Record Protocol", r"^\x16\x03\x02..\x01"),
    ("TLS1.2 Record Protocol", r"^\x16\x03\x03..\x01"),
    ("SSL3.0 CLIENT_HELLO", r"^\x16....\x01...\x03\x00"),
    ("TLS1.0 CLIENT_HELLO", r"^\x16....\x01...\x03\x01"),
    ("TLS1.1 CLIENT_HELLO", r"^\x16....\x01...\x03\x02"),
    ("TLS1.2 CLIENT_HELLO", r"^\x16....\x01...\x03\x03"),
    ("SMB1 COMMAND NEGOTIATE", r"^....\xffSMB\x72"),
    ("SMB1 NT_STATUS Success", r"^....\xffSMB.[\x00-\x0f]"),
    ("SMB1 NT_STATUS Information", r"^....\xffSMB.[\x40-\x4f]"),
    ("SMB1 NT_STATUS Warning", r"^....\xffSMB.[\x80-\x8f]"),
    ("SMB1 NT_STATUS Error", r"^....\xffSMB.[\xc0-\xcf]"),
    ("SMB2 COMMAND NEGOTIATE", r"^\x00...\xfeSMB........\x00\x00"),
    ("SMB2 NT_STATUS Success", r"^\x00...\xfeSMB....[\x00-\x0f]"),
    ("SMB2 NT_STATUS Information", r"^\x00...\xfeSMB....[\x40-\x4f]"),
    ("SMB2 NT_STATUS Warning", r"^\x00...\xfeSMB....[\x80-\x8f]"),
    ("SMB2 NT_STATUS Error", r"^\x00...\xfeSMB....[\xc0-\xcf]"),
    ("MS-TDS PRELOGIN Request", r"^\x12\x01\x00.\x00\x00"),
    ("MS-TDS LOGIN Request", r"^\x10\x01\x00.\x00\x00"),
    ("SOCKS4 NOAUTH Request", r"^\x04\x01\x00\x50"),
    ("SOCKS5 NOAUTH Request", r"^\x05\x01\x00$"), // Tested ok-ish
    ("SOCKS5 USER/PASS Request", r"^\x05\x02\x00\x02$") // possibly broken
  ];
  let io_timeout = Duration::new(300, 0); // 5 minutes

  let mut config_str = String::new();
  match File::open("config.yml") {
      Ok(mut file)   => { file.read_to_string(&mut config_str).unwrap(); },
      Err(err)  => { println!("Unable to open configuration file: {}", err); exit(-1); },
  }

  let docs = YamlLoader::load_from_str(&config_str).unwrap();
  let config = &docs[0];
  //println!("{:?}", config);
  if config["general"].is_badvalue() {
    println!("No 'general' section found in configuration file");
    exit(-1);
  }
  if config["ports"].is_badvalue() {
    println!("No 'ports' section found in configuration file");
    exit(-1);
  }
  if !config["general"]["print_ascii"].is_badvalue() {
    if config["general"]["print_ascii"].as_bool().unwrap() {
      app.print_ascii = true;
      println!("Printing ASCII");
    }
  }
  if !config["general"]["print_binary"].is_badvalue() {
    if config["general"]["print_binary"].as_bool().unwrap() {
      app.print_binary = true;
      println!("Printing binary in hexadecimal");
    }
  }
  if !config["general"]["sql_logging"].is_badvalue() {
    if config["general"]["sql_logging"].as_bool().unwrap() {
      app.sql_logging = true;
      println!("Logging events to portlurker.sqlite");
      let conn = Connection::open("portlurker.sqlite").expect("Failed to open or create database! Check your permissions or disk space.");
      conn.execute("CREATE TABLE IF NOT EXISTS connections (
        id         INTEGER PRIMARY KEY,
        time       INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
        remoteip   TEXT NOT NULL,
        remoteport INTEGER NOT NULL,
        localport  INTEGER NOT NULL
      )", &[]).expect("Failed to create table inside database!");
    }
  }
  let app = app; // Revert to immutable

  let mut patterns = Vec::with_capacity(binary_matches.len());
  for &(_, pattern) in binary_matches.into_iter() {
    patterns.push(pattern);
  }
  let regexset = RegexSetBuilder::new(patterns)
    .unicode(false)
    .dot_matches_new_line(false)
    .build().unwrap();

  println!("\nStarting listeners on the following ports:");

  for port in config["ports"].as_vec().unwrap() {
    if !port["tcp"].is_badvalue() {
      let portno = port["tcp"].as_i64().unwrap();
      println!("TCP port {}", portno);
      let mut banner = Arc::new(String::new());
      if let Some(x) = port["banner"].as_str() {
        Arc::get_mut(& mut banner).unwrap().push_str(x);
        println!("  with banner: {}", *banner);
      }
      let regexset = regexset.clone();
      thread::spawn(move || {
        let server = TcpListener::bind(("0.0.0.0", portno as u16)).unwrap();
        for res in server.incoming() {
          let mut stream = match res {
            Ok(stream) => stream,
            Err(e) => { println!("ACCEPT ERROR TCP {}: {}", portno, e.to_string()); continue; }
          };
          stream.set_read_timeout(Some(io_timeout)).expect("Failed to set read timeout on TcpStream");
          stream.set_write_timeout(Some(io_timeout)).expect("Failed to set write timeout on TcpStream");
          let addr = stream.peer_addr().unwrap();
          println!("CONNECT TCP {} from {}", portno, addr);

          if app.sql_logging {
            #[derive(Debug)]
            struct LoggedConnection {
              remoteip: String,
              remoteport: u16,
              localport: i64
            }

            let newdbentry = LoggedConnection {
              remoteip: addr.ip().to_string(),
              remoteport: addr.port(),
              localport: portno
            };

            let conn = Connection::open("./portlurker.sqlite").unwrap();
            conn.execute("INSERT INTO connections (remoteip, remoteport, localport) VALUES (?1, ?2, ?3)", &[&newdbentry.remoteip, &newdbentry.remoteport, &newdbentry.localport]).expect("Can't write new row into table!");
          }

          let regexset = regexset.clone();
          let banner = banner.clone();
          thread::spawn(move || {
            if banner.len() > 0 {
              match stream.write((*banner).as_bytes()) {
                Ok(_) => {
                  for line in (*banner).lines() {
                    println!("> {}", line);
                  }
                }
                Err(e) => {
                  if e.kind() == io::ErrorKind::WouldBlock { println!("WRITE TIMEOUT TCP {} from {}", portno, addr); }
                  else { println!("WRITE ERROR TCP {} from {}: {}", portno, addr, e.to_string()); }
                  return;
                }
              }
            }
            let mut buf: [u8; 2048] = [0; 2048];
            loop {
              match stream.read(&mut buf) {
                Ok(c) => {
                  if c == 0 {
                    println!("CLOSE TCP {} from {}", portno, addr);
                    break;
                  }
                  let mut printables = Vec::new();
                  let mut found = false;
                  let mut mbfound = false;
                  let mut mbstring = String::new();
                  let mut start = 0;
                  for i in 0..c {
                    if (buf[i] > 31 && buf[i] < 127) || buf[i] == 10 || buf[i] == 13 {
                      if !found {
                        start = i;
                        found = true;
                      }
                    }
                    else {
                      if found {
                        if i-start == 1 {
                          if (start > 0) && (buf[start-1] == 0) {
                            mbstring.push(buf[i-1] as char);
                            if !mbfound { mbfound = true; }
                          }
                        }
                        else { printables.push(&buf[start..i]); }
                        found = false;
                      }
                      else if mbfound {
                        mbstring.push('\n');
                        mbfound = false;
                      }
                    }
                  }
                  if found { printables.push(&buf[start..c]); }
                  if printables.len() == 1 && printables[0].len() == c {
                    if app.print_ascii {
                      let data = String::from_utf8_lossy(printables[0]);
                      for line in data.lines() {
                        println!("| {}", line);
                      }
                    }
                    else { println!("! Read {} bytes of printable ASCII", c); }
                  }
                  else {
                    println!("! Read {} bytes of binary", c);
                    for id in regexset.matches(&buf[..c]).into_iter() {
                      println!("^ Matches pattern {}", binary_matches[id].0);
                    }
                    for printable in printables {
                      if printable.len() > 3 {
                        let data = String::from_utf8_lossy(printable);
                        for line in data.lines() {
                          println!("$ {}", line);
                        }
                      }
                    }
                    for line in mbstring.lines() {
                      if line.len() > 3 { println!("% {}", line); }
                    }
                    if app.print_binary {
                      let hex = to_hex(&buf[..c]);
                      for line in hex.lines() { println!(". {}", line); }
                    }
                  }
                }
                Err(e) => {
                  if e.kind() == io::ErrorKind::WouldBlock { println!("READ TIMEOUT TCP {} from {}", portno, addr); }
                  else { println!("READ ERROR TCP {} from {}: {}", portno, addr, e.to_string()); }
                  break;
                }
              }
              match stream.take_error() {
                Ok(opt) => {
                  if opt.is_some() {
                    println!("ERROR TCP {} from {}: {}", portno, addr, opt.unwrap().to_string());
                    break;
                  }
                }
                Err(_) => {
                  println!("This shouldn't happen...");
                  break;
                }
              }
            }
          });
        }
      });
    }
    else if !port["udp"].is_badvalue() {
      println!("UDP port {}", port["udp"].as_i64().unwrap());
    }
    else {
      println!("Invalid port specification in configuration file");
    }
  }

  loop { thread::sleep(Duration::new(60, 0)); }
}
<commit_msg>Improved SQLite error handling<commit_after>extern crate yaml_rust;
extern crate regex;
extern crate rusqlite;

use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::net::TcpListener;
use std::time::Duration;
use std::sync::Arc;
use std::thread;
use std::process::exit;
use yaml_rust::YamlLoader;
use regex::bytes::RegexSetBuilder;
use rusqlite::Connection;

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

#[derive(Copy, Clone)]
struct App {
  print_ascii: bool,
  print_binary: bool,
  sql_logging: bool
}

fn to_hex(bytes: &[u8]) -> String {
  let mut count = 0;
  let mut result = String::with_capacity(67);
  let mut dotline = String::with_capacity(18);

  for byte in bytes.iter() {
    if count != 0 && count%8 == 0 {
      result.push(' ');
      if count%16 == 0 {
        dotline.push('\n');
        result.push_str(&dotline);
        result.reserve(67);
        dotline.truncate(0);
      }
      else { dotline.push(' '); }
    }
    result.push_str(&format!("{:02X} ", byte));
    if *byte > 31 && *byte < 127 { dotline.push(*byte as char) }
    else if *byte == 0 { dotline.push('-'); }
    else { dotline.push('.'); }
    count += 1;
  }
  while count%16 != 0 {
    if count%8 == 0 { result.push(' '); }
    result.push_str("   ");
    count += 1;
  }
  if dotline.len() != 0 { result.push_str(&dotline); }
  result
}

fn main() {
  let authorstring: String = str::replace(env!("CARGO_PKG_AUTHORS"), ":", "\n");
  println!("Portlurker v{}", VERSION);
  println!("{}", authorstring);
  println!("-----------------------------------------");

  let mut app = App { print_ascii: false, print_binary: false, sql_logging: false };
  let binary_matches = [
    ("SSL3.0 Record Protocol", r"^\x16\x03\x00..\x01"),
    ("TLS1.0 Record Protocol", r"^\x16\x03\x01..\x01"),
    ("TLS1.1 Record Protocol", r"^\x16\x03\x02..\x01"),
    ("TLS1.2 Record Protocol", r"^\x16\x03\x03..\x01"),
    ("SSL3.0 CLIENT_HELLO", r"^\x16....\x01...\x03\x00"),
    ("TLS1.0 CLIENT_HELLO", r"^\x16....\x01...\x03\x01"),
    ("TLS1.1 CLIENT_HELLO", r"^\x16....\x01...\x03\x02"),
    ("TLS1.2 CLIENT_HELLO", r"^\x16....\x01...\x03\x03"),
    ("SMB1 COMMAND NEGOTIATE", r"^....\xffSMB\x72"),
    ("SMB1 NT_STATUS Success", r"^....\xffSMB.[\x00-\x0f]"),
    ("SMB1 NT_STATUS Information", r"^....\xffSMB.[\x40-\x4f]"),
    ("SMB1 NT_STATUS Warning", r"^....\xffSMB.[\x80-\x8f]"),
    ("SMB1 NT_STATUS Error", r"^....\xffSMB.[\xc0-\xcf]"),
    ("SMB2 COMMAND NEGOTIATE", r"^\x00...\xfeSMB........\x00\x00"),
    ("SMB2 NT_STATUS Success", r"^\x00...\xfeSMB....[\x00-\x0f]"),
    ("SMB2 NT_STATUS Information", r"^\x00...\xfeSMB....[\x40-\x4f]"),
    ("SMB2 NT_STATUS Warning", r"^\x00...\xfeSMB....[\x80-\x8f]"),
    ("SMB2 NT_STATUS Error", r"^\x00...\xfeSMB....[\xc0-\xcf]"),
    ("MS-TDS PRELOGIN Request", r"^\x12\x01\x00.\x00\x00"),
    ("MS-TDS LOGIN Request", r"^\x10\x01\x00.\x00\x00"),
    ("SOCKS4 NOAUTH Request", r"^\x04\x01\x00\x50"),
    ("SOCKS5 NOAUTH Request", r"^\x05\x01\x00$"), // Tested ok-ish
    ("SOCKS5 USER/PASS Request", r"^\x05\x02\x00\x02$") // possibly broken
  ];
  let io_timeout = Duration::new(300, 0); // 5 minutes

  let mut config_str = String::new();
  match File::open("config.yml") {
      Ok(mut file) => { file.read_to_string(&mut config_str).unwrap(); },
      Err(err) => { println!("Unable to open configuration file: {}", err); exit(-1); },
  }

  let docs = YamlLoader::load_from_str(&config_str).unwrap();
  let config = &docs[0];
  //println!("{:?}", config);
  if config["general"].is_badvalue() {
    println!("No 'general' section found in configuration file");
    exit(-1);
  }
  if config["ports"].is_badvalue() {
    println!("No 'ports' section found in configuration file");
    exit(-1);
  }
  if !config["general"]["print_ascii"].is_badvalue() {
    if config["general"]["print_ascii"].as_bool().unwrap() {
      app.print_ascii = true;
      println!("Printing ASCII");
    }
  }
  if !config["general"]["print_binary"].is_badvalue() {
    if config["general"]["print_binary"].as_bool().unwrap() {
      app.print_binary = true;
      println!("Printing binary in hexadecimal");
    }
  }
  if !config["general"]["sql_logging"].is_badvalue() {
    if config["general"]["sql_logging"].as_bool().unwrap() {
      app.sql_logging = true;
      println!("Logging events to portlurker.sqlite");
      match Connection::open("portlurker.sqlite") {
        Ok(conn) => { conn.execute("CREATE TABLE IF NOT EXISTS connections (
                      id         INTEGER PRIMARY KEY,
                      time       INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
                      remoteip   TEXT NOT NULL,
                      remoteport INTEGER NOT NULL,
                      localport  INTEGER NOT NULL
                      )", &[]).expect("Failed to create table inside database! Logging may not function correctly!");
        },
        Err(err) => {println!("Failed to open or create database: {} - Continuing without logging", err); app.sql_logging = false;},
      }
    }
  }
  let app = app; // Revert to immutable

  let mut patterns = Vec::with_capacity(binary_matches.len());
  for &(_, pattern) in binary_matches.into_iter() {
    patterns.push(pattern);
  }
  let regexset = RegexSetBuilder::new(patterns)
    .unicode(false)
    .dot_matches_new_line(false)
    .build().unwrap();

  println!("\nStarting listeners on the following ports:");

  for port in config["ports"].as_vec().unwrap() {
    if !port["tcp"].is_badvalue() {
      let portno = port["tcp"].as_i64().unwrap();
      println!("TCP port {}", portno);
      let mut banner = Arc::new(String::new());
      if let Some(x) = port["banner"].as_str() {
        Arc::get_mut(& mut banner).unwrap().push_str(x);
        println!("  with banner: {}", *banner);
      }
      let regexset = regexset.clone();
      thread::spawn(move || {
        let server = TcpListener::bind(("0.0.0.0", portno as u16)).unwrap();
        for res in server.incoming() {
          let mut stream = match res {
            Ok(stream) => stream,
            Err(e) => { println!("ACCEPT ERROR TCP {}: {}", portno, e.to_string()); continue; }
          };
          stream.set_read_timeout(Some(io_timeout)).expect("Failed to set read timeout on TcpStream");
          stream.set_write_timeout(Some(io_timeout)).expect("Failed to set write timeout on TcpStream");
          let addr = stream.peer_addr().unwrap();
          println!("CONNECT TCP {} from {}", portno, addr);

          if app.sql_logging {
            #[derive(Debug)]
            struct LoggedConnection {
              remoteip: String,
              remoteport: u16,
              localport: i64
            }

            let newdbentry = LoggedConnection {
              remoteip: addr.ip().to_string(),
              remoteport: addr.port(),
              localport: portno
            };

            match Connection::open("portlurker.sqlite2") {
              Ok(conn) => { conn.execute("INSERT INTO connections (
                            remoteip, remoteport, localport) VALUES (
                            ?1, ?2, ?3&
                            )", &[&newdbentry.remoteip, &newdbentry.remoteport, &newdbentry.localport]).expect("Can't write new row into table! Subsequent logging may also fail.");},
              Err(err) => {println!("Failed to open database: {} - Continuing without logging", err); let mut app = app ; app.sql_logging = false;},
            }
          }

          let regexset = regexset.clone();
          let banner = banner.clone();
          thread::spawn(move || {
            if banner.len() > 0 {
              match stream.write((*banner).as_bytes()) {
                Ok(_) => {
                  for line in (*banner).lines() {
                    println!("> {}", line);
                  }
                }
                Err(e) => {
                  if e.kind() == io::ErrorKind::WouldBlock { println!("WRITE TIMEOUT TCP {} from {}", portno, addr); }
                  else { println!("WRITE ERROR TCP {} from {}: {}", portno, addr, e.to_string()); }
                  return;
                }
              }
            }
            let mut buf: [u8; 2048] = [0; 2048];
            loop {
              match stream.read(&mut buf) {
                Ok(c) => {
                  if c == 0 {
                    println!("CLOSE TCP {} from {}", portno, addr);
                    break;
                  }
                  let mut printables = Vec::new();
                  let mut found = false;
                  let mut mbfound = false;
                  let mut mbstring = String::new();
                  let mut start = 0;
                  for i in 0..c {
                    if (buf[i] > 31 && buf[i] < 127) || buf[i] == 10 || buf[i] == 13 {
                      if !found {
                        start = i;
                        found = true;
                      }
                    }
                    else {
                      if found {
                        if i-start == 1 {
                          if (start > 0) && (buf[start-1] == 0) {
                            mbstring.push(buf[i-1] as char);
                            if !mbfound { mbfound = true; }
                          }
                        }
                        else { printables.push(&buf[start..i]); }
                        found = false;
                      }
                      else if mbfound {
                        mbstring.push('\n');
                        mbfound = false;
                      }
                    }
                  }
                  if found { printables.push(&buf[start..c]); }
                  if printables.len() == 1 && printables[0].len() == c {
                    if app.print_ascii {
                      let data = String::from_utf8_lossy(printables[0]);
                      for line in data.lines() {
                        println!("| {}", line);
                      }
                    }
                    else { println!("! Read {} bytes of printable ASCII", c); }
                  }
                  else {
                    println!("! Read {} bytes of binary", c);
                    for id in regexset.matches(&buf[..c]).into_iter() {
                      println!("^ Matches pattern {}", binary_matches[id].0);
                    }
                    for printable in printables {
                      if printable.len() > 3 {
                        let data = String::from_utf8_lossy(printable);
                        for line in data.lines() {
                          println!("$ {}", line);
                        }
                      }
                    }
                    for line in mbstring.lines() {
                      if line.len() > 3 { println!("% {}", line); }
                    }
                    if app.print_binary {
                      let hex = to_hex(&buf[..c]);
                      for line in hex.lines() { println!(". {}", line); }
                    }
                  }
                }
                Err(e) => {
                  if e.kind() == io::ErrorKind::WouldBlock { println!("READ TIMEOUT TCP {} from {}", portno, addr); }
                  else { println!("READ ERROR TCP {} from {}: {}", portno, addr, e.to_string()); }
                  break;
                }
              }
              match stream.take_error() {
                Ok(opt) => {
                  if opt.is_some() {
                    println!("ERROR TCP {} from {}: {}", portno, addr, opt.unwrap().to_string());
                    break;
                  }
                }
                Err(_) => {
                  println!("This shouldn't happen...");
                  break;
                }
              }
            }
          });
        }
      });
    }
    else if !port["udp"].is_badvalue() {
      println!("UDP port {}", port["udp"].as_i64().unwrap());
    }
    else {
      println!("Invalid port specification in configuration file");
    }
  }

  loop { thread::sleep(Duration::new(60, 0)); }
}
<|endoftext|>


<commit_before>fn main() {
  let message = [
    "Thanks for installing Platypus!",
    "We're trying to make the world a better place.",
    "We're very happy you've decided to get involved.",
    "Platypie is a work in progress.",
    "If you want to get involved, join us on IRC!",
    "irc.freenode.net/#platypie"
  ];

  for sptr in message.iter() {
    println!("{}",*sptr);
  }
}
<commit_msg>you'd think I'd know my own project's name<commit_after>fn main() {
  let message = [
    "Thanks for installing Platypie!",
    "We're trying to make the world a better place.",
    "We're very happy you've decided to get involved.",
    "Platypie is a work in progress.",
    "If you want to get involved, join us on IRC!",
    "irc.freenode.net/#platypie"
  ];

  for sptr in message.iter() {
    println!("{}",*sptr);
  }
}
<|endoftext|>


<commit_before>use glium;
use glutin;
use rand;
use std;
use time;

use prelude::*;
use raytrace;
use scene;

fn solid_color(r: f32, g: f32, b: f32) -> scene::Texture {
  scene::Texture::SolidColor(RGB { r: r, g: g, b: b })
}

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 600;

pub fn main() {
  use glium::DisplayBuild;

  let window =
    glutin::WindowBuilder::new()
    .with_dimensions(WINDOW_WIDTH, WINDOW_HEIGHT)
    .build_glium()
    .unwrap();

  let mut scene =
    scene::T {
      objects       :
        vec!(
          // red ball
          scene::Object { center: Point::new(-4.0,   -1.0,  -5.0), radius:   1.0, emittance:  0.0, reflectance: 1.0, transmittance: 0.0, shininess: 0.0 , texture: solid_color(1.0, 0.0, 0.0) },
          // blue ball
          scene::Object { center: Point::new(-0.5,   -1.0,  -5.0), radius:   1.0, emittance:  0.0, reflectance: 0.1, transmittance: 0.9, shininess: 0.5, texture: solid_color(0.0, 0.6, 1.0) },
          // frosted glass ball
          scene::Object { center: Point::new(-0.7,   -0.5,  -1.5), radius:   0.5, emittance:  0.0, reflectance: 0.1, transmittance: 0.8, shininess: 0.8, texture: solid_color(0.9, 0.9, 1.0) },
          // glass ball
          scene::Object { center: Point::new( 0.2,   -0.5,  -1.0), radius:   0.5, emittance:  0.0, reflectance: 0.1, transmittance: 0.9, shininess: 2.0 , texture: solid_color(0.9, 0.9, 1.0) },
          // brass ball
          scene::Object { center: Point::new( 3.0,    1.5, -10.0), radius:   4.0, emittance:  0.0, reflectance: 1.0, transmittance: 0.0, shininess: 1.0 , texture: solid_color(1.0, 0.4, 0.1) },
          // small mirror ball
          scene::Object { center: Point::new( 3.0,   -1.0,  -3.5), radius:   1.0, emittance:  0.0, reflectance: 0.9, transmittance: 0.0, shininess: 2.0 , texture: solid_color(1.0, 1.0, 1.0) },
          // light
          scene::Object { center: Point::new(-9.0,   10.0,   0.0), radius:   1.0, emittance:  1.0, reflectance: 0.0, transmittance: 1.0, shininess: 2.0 , texture: solid_color(0.9, 0.9, 1.0) },
          // walls
          scene::Object { center: Point::new( 0.0,    0.0,   0.0), radius:  20.0, emittance:  0.2, reflectance: 0.0, transmittance: 0.0, shininess: 2.0 , texture: solid_color(1.0, 1.0, 1.0) },
          // floor
          scene::Object { center: Point::new( 0.0, -102.0,   0.0), radius: 100.0, emittance:  0.0, reflectance: 1.0, transmittance: 0.0, shininess: 0.5, texture: solid_color(0.4, 0.2, 0.0) },
        ),
      fovy          : std::f32::consts::FRAC_PI_2,
      eye           : Point::new(0.0, 0.0,  0.0),
      look          : Vector::new(0.0, 0.0, -1.0),
      up            : Vector::new(0.0, 1.0,  0.0),
    };

  let inv_min_scale = 1 << 5;
  let w = WINDOW_WIDTH / inv_min_scale;
  let h = WINDOW_HEIGHT / inv_min_scale;
  let max_scale = inv_min_scale << 1;

  let framebuffer_texture = {
    let w = w * max_scale;
    let h = h * max_scale;
    glium::texture::Texture2d::new(
      &window,
      glium::texture::RawImage2d {
        width  : w,
        height : h,
        format : glium::texture::ClientFormat::F32F32F32,
        data   : std::borrow::Cow::Owned(std::iter::repeat((0.0, 0.0, 0.0)).take((w*h) as usize).collect()),
      },
    ).unwrap()
  };

  let mut framebuffer = glium::framebuffer::SimpleFrameBuffer::new(&window, &framebuffer_texture).unwrap();

  let mut rng: rand::XorShiftRng = rand::SeedableRng::from_seed([0x12345678, 0x9abcdef0, 0x13371337, 0x98765432]);

  let mut stationary_frames_drawn = 0;
  loop {
    let scale = std::cmp::min(max_scale, 1 << stationary_frames_drawn);
    let w = w * scale;
    let h = h * scale;

    let before = time::precise_time_ns();
    let rendered = raytrace::scene(&scene, w, h, &mut rng);
    let after = time::precise_time_ns();
    println!("Render took {:?}ms", (after - before) as f32 / 1_000_000.0);

    let rendered =
      glium::texture::Texture2d::with_format(
        &window,
        glium::texture::RawImage2d {
          data: std::borrow::Cow::Owned(rendered.to_vec()),
          width: w,
          height: h,
          format: glium::texture::ClientFormat::F32F32F32,
        },
        glium::texture::UncompressedFloatFormat::F32F32F32,
        glium::texture::MipmapsOption::NoMipmap,
      )
      .unwrap();

    let draw_parameters =
      glium::DrawParameters {
        depth:
          glium::Depth {
            test: glium::DepthTest::Overwrite,
            write: false,
            .. Default::default()
          },
        blend:
          glium::Blend {
            color: glium::BlendingFunction::AlwaysReplace,
            alpha: glium::BlendingFunction::AlwaysReplace,
            constant_value: (0.0, 0.0, 0.0, 0.0),
          },
        .. Default::default()
      };

    let source =
      glium::uniforms::Sampler::new(&rendered)
      .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear)
      .minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear);

    draw(&window, source, &mut framebuffer, &draw_parameters);

    let source =
      glium::uniforms::Sampler::new(&framebuffer_texture)
      .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear)
      .minify_filter(glium::uniforms::MinifySamplerFilter::Linear);

    let mut target = window.draw();
    glium::Surface::clear(&mut target, None, Some((0.0, 0.0, 0.0, 1.0)), false, None, None);
    draw(&window, source, &mut target, &draw_parameters);
    target.finish().unwrap();

    stationary_frames_drawn += 1;

    for event in window.poll_events() {
      // because closures get belligerent about borrowing. Yes, really.
      // I don't make the rules, I just do what makes me hate myself the least.
      macro_rules! move_camera {
        ( $v:expr ) => {
          let v = $v;
          scene.move_camera(&v);
          stationary_frames_drawn = 0;
        };
      }

      match event {
        glutin::Event::Closed => return,
        glutin::Event::KeyboardInput(glium::glutin::ElementState::Pressed, _, Some(key)) => {
          match key {
            glutin::VirtualKeyCode::W => {
              move_camera!(scene.z());
            },
            glutin::VirtualKeyCode::S => {
              move_camera!(-scene.z());
            },
            glutin::VirtualKeyCode::D => {
              move_camera!(scene.x());
            },
            glutin::VirtualKeyCode::A => {
              move_camera!(-scene.x());
            },
            _ => {},
          }
        },
        _ => {},
      }
    }
  }
}

fn draw<'a, Dest: glium::Surface>(
  window: &glium::backend::glutin_backend::GlutinFacade,
  source: glium::uniforms::Sampler<'a, glium::Texture2d>,
  destination: &mut Dest,
  draw_parameters: &glium::DrawParameters,
) {
  // building the vertex buffer, which contains all the vertices that we will draw
  let vertex_buffer = {
    #[derive(Copy, Clone)]
    struct Vertex {
      position: [f32; 2],
      tex_coords: [f32; 2],
    }

    implement_vertex!(Vertex, position, tex_coords);

    glium::VertexBuffer::new(
      window,
      &[
      Vertex { position: [-1.0, -1.0], tex_coords: [0.0, 0.0] },
      Vertex { position: [-1.0,  1.0], tex_coords: [0.0, 1.0] },
      Vertex { position: [ 1.0,  1.0], tex_coords: [1.0, 1.0] },
      Vertex { position: [ 1.0, -1.0], tex_coords: [1.0, 0.0] }
      ]
    ).unwrap()
  };

  // building the index buffer
  let index_buffer =
    glium::IndexBuffer::new(
      window,
      glium::index::PrimitiveType::TriangleStrip,
      &[1 as u16, 2, 0, 3],
    ).unwrap();

  // compiling shaders and linking them together
  let program =
    program!(
      window,
      330 => {
        vertex: "
          #version 330

          uniform mat4 matrix;

          in vec2 position;
          in vec2 tex_coords;

          out vec2 v_tex_coords;

          void main() {
            gl_Position = matrix * vec4(position, 0.0, 1.0);
            v_tex_coords = tex_coords;
          }
        ",

        fragment: "
          #version 330
          uniform sampler2D tex;
          in vec2 v_tex_coords;
          out vec4 f_color;

          void main() {
            f_color = texture(tex, v_tex_coords);
          }
        "
      },
    ).unwrap();

  // building the uniforms
  let uniforms = uniform! {
    matrix: [
      [1.0, 0.0, 0.0, 0.0],
      [0.0, 1.0, 0.0, 0.0],
      [0.0, 0.0, 1.0, 0.0],
      [0.0, 0.0, 0.0, 1.0f32]
    ],
    tex: source,
  };

  destination.draw(
    &vertex_buffer,
    &index_buffer,
    &program,
    &uniforms,
    &draw_parameters,
  ).unwrap();
}
<commit_msg>brass ball is coarser<commit_after>use glium;
use glutin;
use rand;
use std;
use time;

use prelude::*;
use raytrace;
use scene;

fn solid_color(r: f32, g: f32, b: f32) -> scene::Texture {
  scene::Texture::SolidColor(RGB { r: r, g: g, b: b })
}

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 600;

pub fn main() {
  use glium::DisplayBuild;

  let window =
    glutin::WindowBuilder::new()
    .with_dimensions(WINDOW_WIDTH, WINDOW_HEIGHT)
    .build_glium()
    .unwrap();

  let mut scene =
    scene::T {
      objects       :
        vec!(
          // red ball
          scene::Object { center: Point::new(-4.0,   -1.0,  -5.0), radius:   1.0, emittance:  0.0, reflectance: 1.0, transmittance: 0.0, shininess: 0.0 , texture: solid_color(1.0, 0.0, 0.0) },
          // blue ball
          scene::Object { center: Point::new(-0.5,   -1.0,  -5.0), radius:   1.0, emittance:  0.0, reflectance: 0.1, transmittance: 0.9, shininess: 0.5, texture: solid_color(0.0, 0.6, 1.0) },
          // frosted glass ball
          scene::Object { center: Point::new(-0.7,   -0.5,  -1.5), radius:   0.5, emittance:  0.0, reflectance: 0.1, transmittance: 0.8, shininess: 0.8, texture: solid_color(0.9, 0.9, 1.0) },
          // glass ball
          scene::Object { center: Point::new( 0.2,   -0.5,  -1.0), radius:   0.5, emittance:  0.0, reflectance: 0.1, transmittance: 0.9, shininess: 2.0 , texture: solid_color(0.9, 0.9, 1.0) },
          // brass ball
          scene::Object { center: Point::new( 3.0,    1.5, -10.0), radius:   4.0, emittance:  0.0, reflectance: 1.0, transmittance: 0.0, shininess: 0.1 , texture: solid_color(1.0, 0.4, 0.1) },
          // small mirror ball
          scene::Object { center: Point::new( 3.0,   -1.0,  -3.5), radius:   1.0, emittance:  0.0, reflectance: 0.9, transmittance: 0.0, shininess: 2.0 , texture: solid_color(1.0, 1.0, 1.0) },
          // light
          scene::Object { center: Point::new(-9.0,   10.0,   0.0), radius:   1.0, emittance:  1.0, reflectance: 0.0, transmittance: 1.0, shininess: 2.0 , texture: solid_color(0.9, 0.9, 1.0) },
          // walls
          scene::Object { center: Point::new( 0.0,    0.0,   0.0), radius:  20.0, emittance:  0.2, reflectance: 0.0, transmittance: 0.0, shininess: 2.0 , texture: solid_color(1.0, 1.0, 1.0) },
          // floor
          scene::Object { center: Point::new( 0.0, -102.0,   0.0), radius: 100.0, emittance:  0.0, reflectance: 1.0, transmittance: 0.0, shininess: 0.5, texture: solid_color(0.4, 0.2, 0.0) },
        ),
      fovy          : std::f32::consts::FRAC_PI_2,
      eye           : Point::new(0.0, 0.0,  0.0),
      look          : Vector::new(0.0, 0.0, -1.0),
      up            : Vector::new(0.0, 1.0,  0.0),
    };

  let inv_min_scale = 1 << 5;
  let w = WINDOW_WIDTH / inv_min_scale;
  let h = WINDOW_HEIGHT / inv_min_scale;
  let max_scale = inv_min_scale << 1;

  let framebuffer_texture = {
    let w = w * max_scale;
    let h = h * max_scale;
    glium::texture::Texture2d::new(
      &window,
      glium::texture::RawImage2d {
        width  : w,
        height : h,
        format : glium::texture::ClientFormat::F32F32F32,
        data   : std::borrow::Cow::Owned(std::iter::repeat((0.0, 0.0, 0.0)).take((w*h) as usize).collect()),
      },
    ).unwrap()
  };

  let mut framebuffer = glium::framebuffer::SimpleFrameBuffer::new(&window, &framebuffer_texture).unwrap();

  let mut rng: rand::XorShiftRng = rand::SeedableRng::from_seed([0x12345678, 0x9abcdef0, 0x13371337, 0x98765432]);

  let mut stationary_frames_drawn = 0;
  loop {
    let scale = std::cmp::min(max_scale, 1 << stationary_frames_drawn);
    let w = w * scale;
    let h = h * scale;

    let before = time::precise_time_ns();
    let rendered = raytrace::scene(&scene, w, h, &mut rng);
    let after = time::precise_time_ns();
    println!("Render took {:?}ms", (after - before) as f32 / 1_000_000.0);

    let rendered =
      glium::texture::Texture2d::with_format(
        &window,
        glium::texture::RawImage2d {
          data: std::borrow::Cow::Owned(rendered.to_vec()),
          width: w,
          height: h,
          format: glium::texture::ClientFormat::F32F32F32,
        },
        glium::texture::UncompressedFloatFormat::F32F32F32,
        glium::texture::MipmapsOption::NoMipmap,
      )
      .unwrap();

    let draw_parameters =
      glium::DrawParameters {
        depth:
          glium::Depth {
            test: glium::DepthTest::Overwrite,
            write: false,
            .. Default::default()
          },
        blend:
          glium::Blend {
            color: glium::BlendingFunction::AlwaysReplace,
            alpha: glium::BlendingFunction::AlwaysReplace,
            constant_value: (0.0, 0.0, 0.0, 0.0),
          },
        .. Default::default()
      };

    let source =
      glium::uniforms::Sampler::new(&rendered)
      .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear)
      .minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear);

    draw(&window, source, &mut framebuffer, &draw_parameters);

    let source =
      glium::uniforms::Sampler::new(&framebuffer_texture)
      .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear)
      .minify_filter(glium::uniforms::MinifySamplerFilter::Linear);

    let mut target = window.draw();
    glium::Surface::clear(&mut target, None, Some((0.0, 0.0, 0.0, 1.0)), false, None, None);
    draw(&window, source, &mut target, &draw_parameters);
    target.finish().unwrap();

    stationary_frames_drawn += 1;

    for event in window.poll_events() {
      // because closures get belligerent about borrowing. Yes, really.
      // I don't make the rules, I just do what makes me hate myself the least.
      macro_rules! move_camera {
        ( $v:expr ) => {
          let v = $v;
          scene.move_camera(&v);
          stationary_frames_drawn = 0;
        };
      }

      match event {
        glutin::Event::Closed => return,
        glutin::Event::KeyboardInput(glium::glutin::ElementState::Pressed, _, Some(key)) => {
          match key {
            glutin::VirtualKeyCode::W => {
              move_camera!(scene.z());
            },
            glutin::VirtualKeyCode::S => {
              move_camera!(-scene.z());
            },
            glutin::VirtualKeyCode::D => {
              move_camera!(scene.x());
            },
            glutin::VirtualKeyCode::A => {
              move_camera!(-scene.x());
            },
            _ => {},
          }
        },
        _ => {},
      }
    }
  }
}

fn draw<'a, Dest: glium::Surface>(
  window: &glium::backend::glutin_backend::GlutinFacade,
  source: glium::uniforms::Sampler<'a, glium::Texture2d>,
  destination: &mut Dest,
  draw_parameters: &glium::DrawParameters,
) {
  // building the vertex buffer, which contains all the vertices that we will draw
  let vertex_buffer = {
    #[derive(Copy, Clone)]
    struct Vertex {
      position: [f32; 2],
      tex_coords: [f32; 2],
    }

    implement_vertex!(Vertex, position, tex_coords);

    glium::VertexBuffer::new(
      window,
      &[
      Vertex { position: [-1.0, -1.0], tex_coords: [0.0, 0.0] },
      Vertex { position: [-1.0,  1.0], tex_coords: [0.0, 1.0] },
      Vertex { position: [ 1.0,  1.0], tex_coords: [1.0, 1.0] },
      Vertex { position: [ 1.0, -1.0], tex_coords: [1.0, 0.0] }
      ]
    ).unwrap()
  };

  // building the index buffer
  let index_buffer =
    glium::IndexBuffer::new(
      window,
      glium::index::PrimitiveType::TriangleStrip,
      &[1 as u16, 2, 0, 3],
    ).unwrap();

  // compiling shaders and linking them together
  let program =
    program!(
      window,
      330 => {
        vertex: "
          #version 330

          uniform mat4 matrix;

          in vec2 position;
          in vec2 tex_coords;

          out vec2 v_tex_coords;

          void main() {
            gl_Position = matrix * vec4(position, 0.0, 1.0);
            v_tex_coords = tex_coords;
          }
        ",

        fragment: "
          #version 330
          uniform sampler2D tex;
          in vec2 v_tex_coords;
          out vec4 f_color;

          void main() {
            f_color = texture(tex, v_tex_coords);
          }
        "
      },
    ).unwrap();

  // building the uniforms
  let uniforms = uniform! {
    matrix: [
      [1.0, 0.0, 0.0, 0.0],
      [0.0, 1.0, 0.0, 0.0],
      [0.0, 0.0, 1.0, 0.0],
      [0.0, 0.0, 0.0, 1.0f32]
    ],
    tex: source,
  };

  destination.draw(
    &vertex_buffer,
    &index_buffer,
    &program,
    &uniforms,
    &draw_parameters,
  ).unwrap();
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;
#[macro_use]
extern crate log;
extern crate env_logger;
#[macro_use]
extern crate enum_primitive;
extern crate num_traits;
extern crate clap;
extern crate serde_yaml;
extern crate rand;

#[macro_use]
extern crate serde_derive;

#[cfg(test)]
#[macro_use]
extern crate quickcheck;

mod runner;
mod markov;
mod common;

use clap::{App, Arg, SubCommand};
use std::fs::File;
use std::io::{self, Write};
use std::str;

fn word_parser(items: Result<Vec<runner::Word>, io::Error>) -> Vec<runner::Word> {
    match items {
        Ok(val) => val,
        Err(err) => {
            if err.kind() == io::ErrorKind::InvalidData {
                println!("{}", err.get_ref().unwrap());
                std::process::exit(-1);
            } else {
                panic!("Error during parsing: {}", err);
            }
        }
    }
}

fn main() {
    env_logger::init().unwrap();
    let app = App::new("peacenik")
        .version("1.0")
        .author("Tom Parker <palfrey@tevp.net>")
        .about("Beatnik language tools")
        .subcommand(SubCommand::with_name("run")
                        .about("Beatnik interpreter")
                        .arg(Arg::with_name("INPUT")
                                 .help("Sets the input file to use")
                                 .required(true)
                                 .index(1)))
        .subcommand(SubCommand::with_name("wottasquare")
                        .about("Wottasquare interpreter")
                        .arg(Arg::with_name("INPUT")
                                 .help("Sets the input file to use")
                                 .required(true)
                                 .index(1)))
        .subcommand(SubCommand::with_name("wottasquare-dumper")
                        .about("Wottasquare dumper")
                        .arg(Arg::with_name("INPUT")
                                 .help("Sets the input file to use")
                                 .required(true)
                                 .index(1)))
        .subcommand(SubCommand::with_name("generate-markov")
                        .about("Markov chain generator")
                        .arg(Arg::with_name("INPUT")
                                 .short("i")
                                 .takes_value(true)
                                 .help("Sets the input file to use")
                                 .required(true))
                        .arg(Arg::with_name("OUTPUT")
                                 .short("o")
                                 .takes_value(true)
                                 .help("Sets the output file to use")
                                 .required(true)))
        .subcommand(SubCommand::with_name("markov-beatnik")
                        .about("Beatnik from Wottasquare using Markov")
                        .arg(Arg::with_name("INPUT")
                                 .short("i")
                                 .takes_value(true)
                                 .help("Sets the input file to use")
                                 .required(true))
                        .arg(Arg::with_name("MARKOV")
                                 .short("m")
                                 .takes_value(true)
                                 .help("Sets the markov file to use")
                                 .required(true))
                        .arg(Arg::with_name("OUTPUT")
                                 .short("o")
                                 .takes_value(true)
                                 .help("Sets the output file to use")
                                 .required(true)));
    let mut usage = Vec::new();
    app.write_help(&mut usage).unwrap();
    match app.get_matches().subcommand() {
        ("run", Some(args)) => {
            let input_fname = args.value_of("INPUT").expect("input filename");
            let items = runner::get_words_fn(input_fname);
            let words = word_parser(items);
            runner::run_beatnik(&words);
        }
        ("wottasquare", Some(args)) => {
            let input_fname = args.value_of("INPUT").expect("input filename");
            let items = runner::get_wottas_fn(input_fname);
            let words = word_parser(items);
            runner::run_beatnik(&words);
        }
        ("wottasquare-dumper", Some(args)) => {
            let input_fname = args.value_of("INPUT").expect("input filename");
            let items = runner::get_words_fn(input_fname);
            let words = word_parser(items);
            runner::output_wottasquare(words);
        }
        ("generate-markov", Some(args)) => {
            let input_fname = args.value_of("INPUT").unwrap();
            let markov = markov::generate_markov(input_fname).expect("markov");
            let output_fname = args.value_of("OUTPUT").expect("output name");
            let mut buffer = File::create(output_fname).unwrap();
            serde_yaml::to_writer(&mut buffer, &markov).unwrap();
        }
        ("markov-beatnik", Some(args)) => {
            let input_fname = args.value_of("INPUT").unwrap();
            let markov_fname = args.value_of("MARKOV").unwrap();
            let words = runner::get_wottas_fn(input_fname).expect("wottasquare data");
            let markov_data = markov::read_markov(markov_fname).expect("markov data");
            let markov_out = markov::make_beatnik(&words, &markov_data).expect("markov");
            let output_fname = args.value_of("OUTPUT").expect("output name");
            let mut buffer = File::create(output_fname).unwrap();
            buffer.write(markov_out.as_bytes()).unwrap();
        }
        _ => {
            println!("No command!\n");
            println!("{}", str::from_utf8(&usage).unwrap());
        }
    }
}

#[cfg(test)]
mod tests {
    use markov;
    use quickcheck::TestResult;
    use runner;

    quickcheck!{
        fn wotta_two_way(xs: Vec<u8>, source_words: String) -> TestResult {
            let mut info = String::new();
            info.push_str(&format!("Source_words: {:?}\n", source_words));
            let mut markov = markov::MarkovInfo::new();
            let tokens = markov::get_tokens(&source_words).unwrap();
            let mut last = markov::Token::Begin.string();
            for token in tokens {
                let str_token = token.string();
                markov.add_token(last, &str_token);
                last = str_token;
            }
            info.push_str(&format!("Markov: {:?}\n", markov));

            let words = xs.iter()
                .filter(|x| *x !=&0)
                .map(|x| runner::Word{score:*x, word:String::from("")})
                .collect();
            info.push_str(&format!("Score in: {:?}\n", xs));
            let markov_out = markov::make_beatnik(&words, &markov).unwrap();
            info.push_str(&format!("Markov out: {:?}\n", markov_out));
            let words_out = runner::get_words(&markov_out).unwrap();
            info.push_str(&format!("Words out: {:?}\n", words_out));
            let score_out: Vec<u8> = words_out.iter().map(|x|x.score).filter(|x| x !=&0).collect();
            info.push_str(&format!("Score out: {:?}\n", score_out));
            let res = xs.into_iter().filter(|x| x != &0).collect::<Vec<u8>>() == score_out;
            info.push_str(&format!("Res: {}\n", res));
            if res {
                TestResult::passed()
            }
            else {
                TestResult::error(info)
            }
        }
    }
}
<commit_msg>Expand out the dodgy unicode character test failure<commit_after>#[macro_use]
extern crate nom;
#[macro_use]
extern crate log;
extern crate env_logger;
#[macro_use]
extern crate enum_primitive;
extern crate num_traits;
extern crate clap;
extern crate serde_yaml;
extern crate rand;

#[macro_use]
extern crate serde_derive;

#[cfg(test)]
#[macro_use]
extern crate quickcheck;

mod runner;
mod markov;
mod common;

use clap::{App, Arg, SubCommand};
use std::fs::File;
use std::io::{self, Write};
use std::str;

fn word_parser(items: Result<Vec<runner::Word>, io::Error>) -> Vec<runner::Word> {
    match items {
        Ok(val) => val,
        Err(err) => {
            if err.kind() == io::ErrorKind::InvalidData {
                println!("{}", err.get_ref().unwrap());
                std::process::exit(-1);
            } else {
                panic!("Error during parsing: {}", err);
            }
        }
    }
}

fn main() {
    env_logger::init().unwrap();
    let app = App::new("peacenik")
        .version("1.0")
        .author("Tom Parker <palfrey@tevp.net>")
        .about("Beatnik language tools")
        .subcommand(SubCommand::with_name("run")
                        .about("Beatnik interpreter")
                        .arg(Arg::with_name("INPUT")
                                 .help("Sets the input file to use")
                                 .required(true)
                                 .index(1)))
        .subcommand(SubCommand::with_name("wottasquare")
                        .about("Wottasquare interpreter")
                        .arg(Arg::with_name("INPUT")
                                 .help("Sets the input file to use")
                                 .required(true)
                                 .index(1)))
        .subcommand(SubCommand::with_name("wottasquare-dumper")
                        .about("Wottasquare dumper")
                        .arg(Arg::with_name("INPUT")
                                 .help("Sets the input file to use")
                                 .required(true)
                                 .index(1)))
        .subcommand(SubCommand::with_name("generate-markov")
                        .about("Markov chain generator")
                        .arg(Arg::with_name("INPUT")
                                 .short("i")
                                 .takes_value(true)
                                 .help("Sets the input file to use")
                                 .required(true))
                        .arg(Arg::with_name("OUTPUT")
                                 .short("o")
                                 .takes_value(true)
                                 .help("Sets the output file to use")
                                 .required(true)))
        .subcommand(SubCommand::with_name("markov-beatnik")
                        .about("Beatnik from Wottasquare using Markov")
                        .arg(Arg::with_name("INPUT")
                                 .short("i")
                                 .takes_value(true)
                                 .help("Sets the input file to use")
                                 .required(true))
                        .arg(Arg::with_name("MARKOV")
                                 .short("m")
                                 .takes_value(true)
                                 .help("Sets the markov file to use")
                                 .required(true))
                        .arg(Arg::with_name("OUTPUT")
                                 .short("o")
                                 .takes_value(true)
                                 .help("Sets the output file to use")
                                 .required(true)));
    let mut usage = Vec::new();
    app.write_help(&mut usage).unwrap();
    match app.get_matches().subcommand() {
        ("run", Some(args)) => {
            let input_fname = args.value_of("INPUT").expect("input filename");
            let items = runner::get_words_fn(input_fname);
            let words = word_parser(items);
            runner::run_beatnik(&words);
        }
        ("wottasquare", Some(args)) => {
            let input_fname = args.value_of("INPUT").expect("input filename");
            let items = runner::get_wottas_fn(input_fname);
            let words = word_parser(items);
            runner::run_beatnik(&words);
        }
        ("wottasquare-dumper", Some(args)) => {
            let input_fname = args.value_of("INPUT").expect("input filename");
            let items = runner::get_words_fn(input_fname);
            let words = word_parser(items);
            runner::output_wottasquare(words);
        }
        ("generate-markov", Some(args)) => {
            let input_fname = args.value_of("INPUT").unwrap();
            let markov = markov::generate_markov(input_fname).expect("markov");
            let output_fname = args.value_of("OUTPUT").expect("output name");
            let mut buffer = File::create(output_fname).unwrap();
            serde_yaml::to_writer(&mut buffer, &markov).unwrap();
        }
        ("markov-beatnik", Some(args)) => {
            let input_fname = args.value_of("INPUT").unwrap();
            let markov_fname = args.value_of("MARKOV").unwrap();
            let words = runner::get_wottas_fn(input_fname).expect("wottasquare data");
            let markov_data = markov::read_markov(markov_fname).expect("markov data");
            let markov_out = markov::make_beatnik(&words, &markov_data).expect("markov");
            let output_fname = args.value_of("OUTPUT").expect("output name");
            let mut buffer = File::create(output_fname).unwrap();
            buffer.write(markov_out.as_bytes()).unwrap();
        }
        _ => {
            println!("No command!\n");
            println!("{}", str::from_utf8(&usage).unwrap());
        }
    }
}

#[cfg(test)]
mod tests {
    use markov;
    use quickcheck::TestResult;
    use runner;

    fn wotta_two_way(xs: Vec<u8>, source_words: String) -> Result<(), String> {
        let mut info = String::new();
        info.push_str(&format!("Source_words: {:?}\n", source_words));
        let mut markov = markov::MarkovInfo::new();
        let tokens = markov::get_tokens(&source_words).unwrap();
        let mut last = markov::Token::Begin.string();
        for token in tokens {
            let str_token = token.string();
            markov.add_token(last, &str_token);
            last = str_token;
        }
        info.push_str(&format!("Markov: {:?}\n", markov));

        let words = xs.iter()
            .filter(|x| *x != &0)
            .map(|x| {
                     runner::Word {
                         score: *x,
                         word: String::from(""),
                     }
                 })
            .collect();
        info.push_str(&format!("Score in: {:?}\n", xs));
        let markov_out = markov::make_beatnik(&words, &markov).unwrap();
        info.push_str(&format!("Markov out: {:?}\n", markov_out));
        let words_out = runner::get_words(&markov_out).unwrap();
        info.push_str(&format!("Words out: {:?}\n", words_out));
        let score_out: Vec<u8> = words_out.iter()
            .map(|x| x.score)
            .filter(|x| x != &0)
            .collect();
        info.push_str(&format!("Score out: {:?}\n", score_out));
        let res = xs.into_iter().filter(|x| x != &0).collect::<Vec<u8>>() == score_out;
        info.push_str(&format!("Res: {}\n", res));
        if res { Ok(()) } else { Err(info) }
    }

    #[test]
    fn test_wotta_two_way_utf() {
        wotta_two_way(vec![3], String::from("ŉb")).unwrap();
    }

    quickcheck!{
        fn wotta_two_way_qc(xs: Vec<u8>, source_words: String) -> TestResult {
            let res = wotta_two_way(xs, source_words);
            match res {
                Ok(_) => TestResult::passed(),
                Err(info) => TestResult::error(info)
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate ansi_term;
extern crate argparse;
extern crate hyper;
extern crate libsnatch;

use ansi_term::Colour::{Green, Yellow, Red};
use argparse::{ArgumentParser, Store, StoreTrue};
use hyper::client::Client;
use libsnatch::{Bytes, Chunks};
use libsnatch::client::GetResponse;
use libsnatch::contentlength::GetContentLength;
use libsnatch::download::download_chunks;
use libsnatch::http_version::ValidateHttpVersion;
use libsnatch::write::write_file;
use std::fs::File;
use std::io;
use std::sync::{Arc, Mutex};
use std::path::Path;
use std::process::exit;

fn main() {

    let mut file = String::from("");
    let mut threads: usize = 4;
    let mut url = String::from("");
    let mut verbose = false;

    {
        let mut argparse = ArgumentParser::new();
        argparse.set_description("Snatch, a simple, fast and interruptable download accelerator, \
                                  written in Rust.");
        argparse.refer(&mut file)
            .add_option(&["-f", "--file"],
                        Store,
                        "The local file to save the remote content file")
            .required();
        argparse.refer(&mut threads)
            .add_option(&["-t", "--threads"],
                        Store,
                        "Number of threads available to download");
        argparse.refer(&mut url)
            .add_option(&["-u", "--url"], Store, "Remote content URL to download")
            .required();
        argparse.refer(&mut verbose)
            .add_option(&["-v", "--verbose"], StoreTrue, "Verbose mode");
        argparse.parse_args_or_exit();
    }

    let hyper_client = Client::new();

    // Get the first response from the server
    let client_response = hyper_client.get_head_response(&url).unwrap();

    print!("# Waiting a response from the remote server... ");

    if !client_response.version.greater_than_http_11() {
        println!("{}",
                 Yellow.bold()
                     .paint("OK (HTTP version <= 1.0 detected)"));
    } else {
        println!("{}", Green.bold().paint("OK !"));
    }

    let local_path = Path::new(&file);

    if local_path.exists() {
        if local_path.is_dir() {
            panic!(Red.bold()
                .paint("[ERROR] The local path to store the remote content is already exists, \
                        and is a directory!"));
        }
        println!("{}",
                 Red.bold()
                     .paint("[WARNING] The path to store the file already exists! Do you want \
                             to override it? [y/N]"));
        {
            let mut user_input = String::new();
            io::stdin()
                .read_line(&mut user_input)
                .ok()
                .expect("[ERROR] Couldn't read line!");
            user_input = String::from(user_input.trim());
            if !(user_input == "y" || user_input == "Y") {
                exit(0);
            }
        }
    }

    let remote_content_length = match client_response.headers.get_content_length() {
        Some(remote_content_length) => remote_content_length,
        None => {
            println!("{}",
                     Red.bold()
                         .paint("[ERROR] Cannot get the content length of the remote content, \
                                 from the server."));
            exit(1);
        }
    };

    println!("# Remote content length: {:?} MB",
             (remote_content_length / 1000000) as Bytes);

    let mut core_chunks = Chunks::with_capacity(threads);

    for _ in 0..threads {
        core_chunks.push(Vec::new());
    }

    let mut shared_chunks = Arc::new(Mutex::new(core_chunks));

    download_chunks(remote_content_length,
                    &mut shared_chunks,
                    threads as u64,
                    &url);

    let mut local_file = File::create(local_path).expect("[ERROR] Cannot create a file !");

    match write_file(&mut local_file, &shared_chunks) {
        Ok(()) => println!("{}", Green.bold().paint("Chunks have been successfuly saved!")),
        Err(error) => println!("[ERROR] {}", error),
    }

}
<commit_msg>Infer filename from URL (issue #38)<commit_after>extern crate ansi_term;
extern crate argparse;
extern crate hyper;
extern crate libsnatch;

use ansi_term::Colour::{Green, Yellow, Red};
use argparse::{ArgumentParser, Store, StoreTrue};
use hyper::client::Client;
use libsnatch::{Bytes, Chunks};
use libsnatch::client::GetResponse;
use libsnatch::contentlength::GetContentLength;
use libsnatch::download::download_chunks;
use libsnatch::http_version::ValidateHttpVersion;
use libsnatch::write::write_file;
use std::fs::File;
use std::io;
use std::sync::{Arc, Mutex};
use std::path::Path;
use std::process::exit;

fn main() {

    let mut file = String::from("");
    let mut threads: usize = 4;
    let mut url = String::from("");
    let mut verbose = false;

    {
        let mut argparse = ArgumentParser::new();
        argparse.set_description("Snatch, a simple, fast and interruptable download accelerator, \
                                  written in Rust.");
        argparse.refer(&mut file)
            .add_option(&["-f", "--file"],
                        Store,
                        "The local file to save the remote content file");
        argparse.refer(&mut threads)
            .add_option(&["-t", "--threads"],
                        Store,
                        "Number of threads available to download");
        argparse.refer(&mut url)
            .add_option(&["-u", "--url"], Store, "Remote content URL to download")
            .required();
        argparse.refer(&mut verbose)
            .add_option(&["-v", "--verbose"], StoreTrue, "Verbose mode");
        argparse.parse_args_or_exit();
    }

    let hyper_client = Client::new();

    // Get the first response from the server
    let client_response = hyper_client.get_head_response(&url).unwrap();

    print!("# Waiting a response from the remote server... ");

    if !client_response.version.greater_than_http_11() {
        println!("{}",
                 Yellow.bold()
                     .paint("OK (HTTP version <= 1.0 detected)"));
    } else {
        println!("{}", Green.bold().paint("OK !"));
    }

    // If no filename has been given, infer it
    if file == "" {
        file = match url.split('/').last() {
            Some(filename) => String::from(filename),
            None => String::from("index.html"),
        }
    }

    let local_path = Path::new(&file);

    if local_path.exists() {
        if local_path.is_dir() {
            panic!(Red.bold()
                .paint("[ERROR] The local path to store the remote content is already exists, \
                        and is a directory!"));
        }
        println!("{}",
                 Red.bold()
                     .paint("[WARNING] The path to store the file already exists! Do you want \
                             to override it? [y/N]"));
        {
            let mut user_input = String::new();
            io::stdin()
                .read_line(&mut user_input)
                .ok()
                .expect("[ERROR] Couldn't read line!");
            user_input = String::from(user_input.trim());
            if !(user_input == "y" || user_input == "Y") {
                exit(0);
            }
        }
    }

    let remote_content_length = match client_response.headers.get_content_length() {
        Some(remote_content_length) => remote_content_length,
        None => {
            println!("{}",
                     Red.bold()
                         .paint("[ERROR] Cannot get the content length of the remote content, \
                                 from the server."));
            exit(1);
        }
    };

    println!("# Remote content length: {:?} MB",
             (remote_content_length / 1000000) as Bytes);

    let mut core_chunks = Chunks::with_capacity(threads);

    for _ in 0..threads {
        core_chunks.push(Vec::new());
    }

    let mut shared_chunks = Arc::new(Mutex::new(core_chunks));

    download_chunks(remote_content_length,
                    &mut shared_chunks,
                    threads as u64,
                    &url);

    let mut local_file = File::create(local_path).expect("[ERROR] Cannot create a file !");

    match write_file(&mut local_file, &shared_chunks) {
        Ok(()) => println!("{}", Green.bold().paint("Chunks have been successfuly saved!")),
        Err(error) => println!("[ERROR] {}", error),
    }

}
<|endoftext|>


<commit_before>#![feature(box_syntax)]
// we have to use the old process module, because the new one doesn't support
// inheritfd, which is needed for process piping
#![allow(deprecated)]
#![feature(path_relative_from)]
#![feature(unsafe_destructor)]
#![feature(unboxed_closures)]
#![feature(collections)]
#![feature(core)]
#![feature(path_ext)]
#![feature(io)]
#![feature(old_io)]
#![feature(old_path)]
#![feature(libc)]
#![feature(std_misc)]
#![feature(unicode)]
#![feature(rustc_private)]
#![feature(plugin)]
#![plugin(regex_macros)]
extern crate sodiumoxide;
extern crate libc;
extern crate serialize;
extern crate unicode;
extern crate regex;
extern crate core;
#[no_link]
extern crate regex_macros;

use reader::*;
use constants::*;
use builtins::*;
use types::*;
use ast::*;
use env::*;
use handlers::*;

use types::InputValue::*;

mod constants;
#[macro_use]
mod util;
mod termios;
mod signal;
mod controls;
mod input;
mod reader;
mod script;
mod builtins;
mod command;
mod types;
mod env;
mod ioctl;
mod ast;
mod handlers;

// public so no warnings when we run tests
pub fn main() {
    let mut reader = LineReader::new();
    let mut env = WashEnv::new();
    let mut ast = AST::new();
    let mut cleaned_jobs;
    match load_builtins(&mut env) {
        Err(e) => env.errf(format_args!("Could not load builtings: {}\n", e)),
        _ => {}
    }
    load_handlers(&mut ast);
    env.update_terminal();
    loop {
        env.flush();
        cleaned_jobs = env.clean_jobs();
        match cleaned_jobs {
            WashArgs::Long(v) => {
                for status in v.iter() {
                    env.outf(format_args!("{}\n", status.flatten()));
                }
            },
            _ => {/* nothing */}
        }
        if ast.in_block() {
            match env.runf(&format!("subprompt"), &WashArgs::Empty) {
                Err(_) => reader.controls.outs("prompt failed => run("),
                Ok(v) => reader.controls.outs(v.flatten().as_slice())
            }
        } else {
            match env.runf(&format!("prompt"), &WashArgs::Empty) {
                Err(_) => reader.controls.outs("prompt failed => run("),
                Ok(v) => reader.controls.outs(v.flatten().as_slice())
            }
        }
        match reader.read_line() {
            None => {
                if reader.eof {
                    break;
                } else if !reader.line.is_empty() {
                    env.outc(BEL);
                    reader.restart();
                } else {
                    env.outc(NL);
                    reader.clear();
                }
            },
            Some(mut line) => {
                env.outc(NL);
                match ast.add_line(&mut line) {
                    Err(ref e) if *e == STOP => {
                        // the silent error
                        ast.clear();
                    },
                    Err(e) => {
                        println!("Error: {}", e);
                        ast.clear();
                    },
                    Ok(_) => {
                        if !ast.in_block() {
                            println!("{:?}", ast);
                            match ast.optimize() {
                                Err(e) => {
                                    println!("Optimization error: {}", e);
                                },
                                Ok(_) => {
                                    //println!("{:?}", ast);
                                }
                            }
                            match ast.into_runner().evaluate(&WashArgs::Empty, &mut env) {
                                Err(ref e) if *e == STOP => {
                                    // the silent error
                                }
                                Err(e) => {
                                    println!("Error: {}", e);
                                },
                                Ok(WashArgs::Empty) => {
                                    // print nothing
                                },
                                Ok(v) => {
                                    println!("{}", v.flatten());
                                }
                            };
                        }
                    }
                }
                reader.clear();
            }
        }
    }
    env.outs("\nExiting\n");
    env.flush();
}
<commit_msg>Remove debug printing<commit_after>#![feature(box_syntax)]
// we have to use the old process module, because the new one doesn't support
// inheritfd, which is needed for process piping
#![allow(deprecated)]
#![feature(path_relative_from)]
#![feature(unsafe_destructor)]
#![feature(unboxed_closures)]
#![feature(collections)]
#![feature(core)]
#![feature(path_ext)]
#![feature(io)]
#![feature(old_io)]
#![feature(old_path)]
#![feature(libc)]
#![feature(std_misc)]
#![feature(unicode)]
#![feature(rustc_private)]
#![feature(plugin)]
#![plugin(regex_macros)]
extern crate sodiumoxide;
extern crate libc;
extern crate serialize;
extern crate unicode;
extern crate regex;
extern crate core;
#[no_link]
extern crate regex_macros;

use reader::*;
use constants::*;
use builtins::*;
use types::*;
use ast::*;
use env::*;
use handlers::*;

use types::InputValue::*;

mod constants;
#[macro_use]
mod util;
mod termios;
mod signal;
mod controls;
mod input;
mod reader;
mod script;
mod builtins;
mod command;
mod types;
mod env;
mod ioctl;
mod ast;
mod handlers;

// public so no warnings when we run tests
pub fn main() {
    let mut reader = LineReader::new();
    let mut env = WashEnv::new();
    let mut ast = AST::new();
    let mut cleaned_jobs;
    match load_builtins(&mut env) {
        Err(e) => env.errf(format_args!("Could not load builtings: {}\n", e)),
        _ => {}
    }
    load_handlers(&mut ast);
    env.update_terminal();
    loop {
        env.flush();
        cleaned_jobs = env.clean_jobs();
        match cleaned_jobs {
            WashArgs::Long(v) => {
                for status in v.iter() {
                    env.outf(format_args!("{}\n", status.flatten()));
                }
            },
            _ => {/* nothing */}
        }
        if ast.in_block() {
            match env.runf(&format!("subprompt"), &WashArgs::Empty) {
                Err(_) => reader.controls.outs("prompt failed => run("),
                Ok(v) => reader.controls.outs(v.flatten().as_slice())
            }
        } else {
            match env.runf(&format!("prompt"), &WashArgs::Empty) {
                Err(_) => reader.controls.outs("prompt failed => run("),
                Ok(v) => reader.controls.outs(v.flatten().as_slice())
            }
        }
        match reader.read_line() {
            None => {
                if reader.eof {
                    break;
                } else if !reader.line.is_empty() {
                    env.outc(BEL);
                    reader.restart();
                } else {
                    env.outc(NL);
                    reader.clear();
                }
            },
            Some(mut line) => {
                env.outc(NL);
                match ast.add_line(&mut line) {
                    Err(ref e) if *e == STOP => {
                        // the silent error
                        ast.clear();
                    },
                    Err(e) => {
                        println!("Error: {}", e);
                        ast.clear();
                    },
                    Ok(_) => {
                        if !ast.in_block() {
                            //println!("{:?}", ast);
                            match ast.optimize() {
                                Err(e) => {
                                    println!("Optimization error: {}", e);
                                },
                                Ok(_) => {
                                    //println!("{:?}", ast);
                                }
                            }
                            match ast.into_runner().evaluate(&WashArgs::Empty, &mut env) {
                                Err(ref e) if *e == STOP => {
                                    // the silent error
                                }
                                Err(e) => {
                                    println!("Error: {}", e);
                                },
                                Ok(WashArgs::Empty) => {
                                    // print nothing
                                },
                                Ok(v) => {
                                    println!("{}", v.flatten());
                                }
                            };
                        }
                    }
                }
                reader.clear();
            }
        }
    }
    env.outs("\nExiting\n");
    env.flush();
}
<|endoftext|>


<commit_before>use std::env;
use std::path::PathBuf;
use std::process;
use std::{cell::RefCell, str::FromStr};

use getopts::Options;
use hprof::Profiler;
use libgir::{self as gir, Config, Library, WorkMode};

fn print_usage(program: &str, opts: Options) {
    let brief = format!(
        "Usage: {program} [options] [<library> <version>]
       {program} (-h | --help)",
        program = program
    );
    print!("{}", opts.usage(&brief));
}

trait OptionStr {
    fn as_str_ref(&self) -> Option<&str>;
}

impl<S: AsRef<str>> OptionStr for Option<S> {
    fn as_str_ref(&self) -> Option<&str> {
        self.as_ref().map(|string| string.as_ref())
    }
}

#[allow(clippy::large_enum_variant)]
enum RunKind {
    Config(Config),
    CheckGirFile(String),
}

fn build_config() -> Result<RunKind, String> {
    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();

    let mut options = Options::new();
    options.optopt(
        "c",
        "config",
        "Config file path (default: Gir.toml)",
        "CONFIG",
    );
    options.optflag("h", "help", "Show this message");
    options.optopt("d", "gir-directory", "Directory for girs", "GIRSPATH");
    options.optopt(
        "m",
        "mode",
        "Work mode: doc, normal, sys or not_bound",
        "MODE",
    );
    options.optopt("o", "target", "Target path", "PATH");
    options.optopt("p", "doc-target-path", "Doc target path", "PATH");
    options.optflag("b", "make-backup", "Make backup before generating");
    options.optflag("s", "stats", "Show statistics");
    options.optflag("", "disable-format", "Disable formatting generated code");
    options.optopt(
        "",
        "check-gir-file",
        "Check if the given `.gir` file is valid",
        "PATH",
    );

    let matches = match options.parse(&args[1..]) {
        Ok(matches) => matches,
        Err(e) => return Err(e.to_string()),
    };

    if let Some(check_gir_file) = matches.opt_str("check-gir-file") {
        return Ok(RunKind::CheckGirFile(check_gir_file));
    }

    if matches.opt_present("h") {
        print_usage(&program, options);
        process::exit(0);
    }

    let work_mode = match matches.opt_str("m") {
        None => None,
        Some(s) => match WorkMode::from_str(&s) {
            Ok(w) => Some(w),
            Err(e) => {
                eprintln!("Error (switching to default work mode): {}", e);
                None
            }
        },
    };

    Config::new(
        matches.opt_str("c").as_str_ref(),
        work_mode,
        matches.opt_str("d").as_str_ref(),
        matches.free.get(0).as_str_ref(),
        matches.free.get(1).as_str_ref(),
        matches.opt_str("o").as_str_ref(),
        matches.opt_str("doc-target-path").as_str_ref(),
        matches.opt_present("b"),
        matches.opt_present("s"),
        matches.opt_present("disable-format"),
    )
    .map(RunKind::Config)
}

#[cfg_attr(test, allow(dead_code))]
fn main() {
    if let Err(ref e) = do_main() {
        eprintln!("{}", e);

        ::std::process::exit(1);
    }
}

fn run_check(check_gir_file: &str) -> Result<(), String> {
    let path = PathBuf::from(check_gir_file);
    if !path.is_file() {
        return Err(format!("`{}`: file not found", check_gir_file));
    }
    let lib_name = match path.file_stem() {
        Some(f) => f,
        None => return Err(format!("Failed to get file stem from `{}`", check_gir_file)),
    };
    let lib_name = match lib_name.to_str() {
        Some(l) => l,
        None => return Err("failed to convert OsStr to str".to_owned()),
    };
    let mut library = Library::new(lib_name);
    let parent = match path.parent() {
        Some(p) => p,
        None => {
            return Err(format!(
                "Failed to get parent directory from `{}`",
                check_gir_file
            ))
        }
    };

    library.read_file(&parent, &mut vec![lib_name.to_owned()])
}

fn do_main() -> Result<(), String> {
    if std::env::var_os("RUST_LOG").is_none() {
        std::env::set_var("RUST_LOG", "gir=warn");
        std::env::set_var("RUST_LOG", "libgir=warn");
    }
    env_logger::init();

    let mut cfg = match build_config() {
        Ok(RunKind::CheckGirFile(check_gir_file)) => return run_check(&check_gir_file),
        Ok(RunKind::Config(cfg)) => cfg,
        Err(err) => return Err(err),
    };
    cfg.check_disable_format();

    let statistics = Profiler::new("Gir");
    statistics.start_frame();

    let watcher_total = statistics.enter("Total");

    let mut library;

    {
        let _watcher = statistics.enter("Loading");

        library = Library::new(&cfg.library_name);
        library.read_file(&cfg.girs_dir, &mut vec![cfg.library_full_name()])?;
    }

    {
        let _watcher = statistics.enter("Preprocessing");
        library.preprocessing(cfg.work_mode);
    }

    {
        let _watcher = statistics.enter("Update library by config");
        gir::update_version::apply_config(&mut library, &cfg);
    }

    {
        let _watcher = statistics.enter("Postprocessing");
        library.postprocessing(&cfg);
    }

    {
        let _watcher = statistics.enter("Resolving type ids");
        cfg.resolve_type_ids(&library);
    }

    {
        let _watcher = statistics.enter("Checking versions");
        gir::update_version::check_function_real_version(&mut library);
    }

    let mut env;

    {
        let _watcher = statistics.enter("Namespace/symbol/class analysis");

        let namespaces = gir::namespaces_run(&library);
        let symbols = gir::symbols_run(&library, &namespaces);
        let class_hierarchy = gir::class_hierarchy_run(&library);

        env = gir::Env {
            library,
            config: cfg,
            namespaces,
            symbols: RefCell::new(symbols),
            class_hierarchy,
            analysis: Default::default(),
        };
    }

    if env.config.work_mode != WorkMode::Sys {
        let _watcher = statistics.enter("Analyzing");
        gir::analysis_run(&mut env);
    }

    if env.config.work_mode != WorkMode::DisplayNotBound {
        let _watcher = statistics.enter("Generating");
        gir::codegen_generate(&env);
    }

    if !env.config.disable_format && env.config.work_mode.is_generate_rust_files() {
        let _watcher = statistics.enter("Formatting");
        gir::fmt::format(&env.config.target_path);
    }

    drop(watcher_total);
    statistics.end_frame();

    if env.config.show_statistics {
        statistics.print_timing();
    }
    if env.config.work_mode == WorkMode::DisplayNotBound {
        env.library.show_non_bound_types(&env);
    }

    Ok(())
}
<commit_msg>Minor cleanups and simplifications<commit_after>use std::env;
use std::path::PathBuf;
use std::process;
use std::{cell::RefCell, str::FromStr};

use getopts::Options;
use hprof::Profiler;
use libgir::{self as gir, Config, Library, WorkMode};

fn print_usage(program: &str, opts: Options) {
    let brief = format!(
        "Usage: {program} [options] [<library> <version>]
       {program} (-h | --help)",
        program = program
    );
    print!("{}", opts.usage(&brief));
}

trait OptionStr {
    fn as_str_ref(&self) -> Option<&str>;
}

impl<S: AsRef<str>> OptionStr for Option<S> {
    fn as_str_ref(&self) -> Option<&str> {
        self.as_ref().map(|string| string.as_ref())
    }
}

#[allow(clippy::large_enum_variant)]
enum RunKind {
    Config(Config),
    CheckGirFile(String),
}

fn build_config() -> Result<RunKind, String> {
    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();

    let mut options = Options::new();
    options.optopt(
        "c",
        "config",
        "Config file path (default: Gir.toml)",
        "CONFIG",
    );
    options.optflag("h", "help", "Show this message");
    options.optopt("d", "gir-directory", "Directory for girs", "GIRSPATH");
    options.optopt(
        "m",
        "mode",
        "Work mode: doc, normal, sys or not_bound",
        "MODE",
    );
    options.optopt("o", "target", "Target path", "PATH");
    options.optopt("p", "doc-target-path", "Doc target path", "PATH");
    options.optflag("b", "make-backup", "Make backup before generating");
    options.optflag("s", "stats", "Show statistics");
    options.optflag("", "disable-format", "Disable formatting generated code");
    options.optopt(
        "",
        "check-gir-file",
        "Check if the given `.gir` file is valid",
        "PATH",
    );

    let matches = match options.parse(&args[1..]) {
        Ok(matches) => matches,
        Err(e) => return Err(e.to_string()),
    };

    if let Some(check_gir_file) = matches.opt_str("check-gir-file") {
        return Ok(RunKind::CheckGirFile(check_gir_file));
    }

    if matches.opt_present("h") {
        print_usage(&program, options);
        process::exit(0);
    }

    let work_mode = match matches.opt_str("m") {
        None => None,
        Some(s) => match WorkMode::from_str(&s) {
            Ok(w) => Some(w),
            Err(e) => {
                eprintln!("Error (switching to default work mode): {}", e);
                None
            }
        },
    };

    Config::new(
        matches.opt_str("c").as_str_ref(),
        work_mode,
        matches.opt_str("d").as_str_ref(),
        matches.free.get(0).as_str_ref(),
        matches.free.get(1).as_str_ref(),
        matches.opt_str("o").as_str_ref(),
        matches.opt_str("doc-target-path").as_str_ref(),
        matches.opt_present("b"),
        matches.opt_present("s"),
        matches.opt_present("disable-format"),
    )
    .map(RunKind::Config)
}

#[cfg_attr(test, allow(dead_code))]
fn main() {
    if let Err(ref e) = do_main() {
        eprintln!("{}", e);

        ::std::process::exit(1);
    }
}

fn run_check(check_gir_file: &str) -> Result<(), String> {
    let path = PathBuf::from(check_gir_file);
    if !path.is_file() {
        return Err(format!("`{}`: file not found", check_gir_file));
    }
    let lib_name = match path.file_stem() {
        Some(f) => f,
        None => return Err(format!("Failed to get file stem from `{}`", check_gir_file)),
    };
    let lib_name = match lib_name.to_str() {
        Some(l) => l,
        None => return Err("failed to convert OsStr to str".to_owned()),
    };
    let mut library = Library::new(lib_name);
    let parent = match path.parent() {
        Some(p) => p,
        None => {
            return Err(format!(
                "Failed to get parent directory from `{}`",
                check_gir_file
            ))
        }
    };

    library.read_file(&parent, &mut vec![lib_name.to_owned()])
}

fn do_main() -> Result<(), String> {
    if std::env::var_os("RUST_LOG").is_none() {
        std::env::set_var("RUST_LOG", "gir=warn");
        std::env::set_var("RUST_LOG", "libgir=warn");
    }
    env_logger::init();

    let mut cfg = match build_config() {
        Ok(RunKind::CheckGirFile(check_gir_file)) => return run_check(&check_gir_file),
        Ok(RunKind::Config(cfg)) => cfg,
        Err(err) => return Err(err),
    };
    cfg.check_disable_format();

    let statistics = Profiler::new("Gir");
    statistics.start_frame();

    let watcher_total = statistics.enter("Total");

    let mut library = {
        let _watcher = statistics.enter("Loading");

        let mut library = Library::new(&cfg.library_name);
        library.read_file(&cfg.girs_dir, &mut vec![cfg.library_full_name()])?;
        library
    };

    {
        let _watcher = statistics.enter("Preprocessing");
        library.preprocessing(cfg.work_mode);
    }

    {
        let _watcher = statistics.enter("Update library by config");
        gir::update_version::apply_config(&mut library, &cfg);
    }

    {
        let _watcher = statistics.enter("Postprocessing");
        library.postprocessing(&cfg);
    }

    {
        let _watcher = statistics.enter("Resolving type ids");
        cfg.resolve_type_ids(&library);
    }

    {
        let _watcher = statistics.enter("Checking versions");
        gir::update_version::check_function_real_version(&mut library);
    }

    let mut env = {
        let _watcher = statistics.enter("Namespace/symbol/class analysis");

        let namespaces = gir::namespaces_run(&library);
        let symbols = gir::symbols_run(&library, &namespaces);
        let class_hierarchy = gir::class_hierarchy_run(&library);

        gir::Env {
            library,
            config: cfg,
            namespaces,
            symbols: RefCell::new(symbols),
            class_hierarchy,
            analysis: Default::default(),
        }
    };

    if env.config.work_mode != WorkMode::Sys {
        let _watcher = statistics.enter("Analyzing");
        gir::analysis_run(&mut env);
    }

    if env.config.work_mode != WorkMode::DisplayNotBound {
        let _watcher = statistics.enter("Generating");
        gir::codegen_generate(&env);
    }

    if !env.config.disable_format && env.config.work_mode.is_generate_rust_files() {
        let _watcher = statistics.enter("Formatting");
        gir::fmt::format(&env.config.target_path);
    }

    drop(watcher_total);
    statistics.end_frame();

    if env.config.show_statistics {
        statistics.print_timing();
    }
    if env.config.work_mode == WorkMode::DisplayNotBound {
        env.library.show_non_bound_types(&env);
    }

    Ok(())
}
<|endoftext|>


<commit_before><commit_msg>updated to new timely<commit_after><|endoftext|>


<commit_before>use std::env;
use std::collections::HashMap;
#[allow(dead_code)]
struct Operator {
    precedence: i32,
    func: Box<Fn(f32, f32) -> f32>
}

fn get_operators () -> HashMap<char, Operator> {
    let multiply = Operator {
        precedence: 3,
        func: Box::new(move |a: f32, b:f32| a * b)
    };

    let divide = Operator {
        precedence: 3,
        func: Box::new(move |a: f32, b:f32| a / b)
    };

    let add = Operator {
        precedence: 4,
        func: Box::new(move |a: f32, b:f32| a + b)
    };

    let subtract = Operator {
        precedence: 4,
        func: Box::new(move |a: f32, b:f32| a - b)
    };

    let mut operators = HashMap::new();

    operators.insert('*', multiply);
    operators.insert('/', divide);
    operators.insert('+', add);
    operators.insert('-', subtract);

    operators
}

fn main () {
    let args: Vec<_> = env::args().collect();
    let tokens: Vec<&str> = args[1].split(" ").collect();
    let mut operator_stack: Vec<char> = vec![];
    let mut output: Vec<String> = vec![];
    let operators = get_operators();

    for token in tokens {
        let maybe_int = token.parse::<i32>();

        match maybe_int {
            Ok(_) => output.push(token.to_string()),
            Err(_) => {
                let o1_char = token.to_string().pop().unwrap();
                let o1 = operators.get(&o1_char).unwrap();

                while !operator_stack.is_empty() {
                    let o2_char = operator_stack[operator_stack.len() - 1];
                    let o2 = operators.get(&o2_char).unwrap();
                    if o1.precedence >= o2.precedence {
                        let popped_o2_char = operator_stack.pop().unwrap().to_string();
                        output.push(popped_o2_char);
                    } else {
                        break;
                    }
                }

                operator_stack.push(o1_char);
            }
        }
    }

    while !operator_stack.is_empty() {
        let op = operator_stack.pop().unwrap().to_string();
        output.push(op);
    }

    println!("{:?}", output);
}
<commit_msg>Apparently 'if let' is cleaner???<commit_after>use std::env;
use std::collections::HashMap;
#[allow(dead_code)]
struct Operator {
    precedence: i32,
    func: Box<Fn(f32, f32) -> f32>
}

fn get_operators () -> HashMap<char, Operator> {
    let multiply = Operator {
        precedence: 3,
        func: Box::new(move |a: f32, b:f32| a * b)
    };

    let divide = Operator {
        precedence: 3,
        func: Box::new(move |a: f32, b:f32| a / b)
    };

    let add = Operator {
        precedence: 4,
        func: Box::new(move |a: f32, b:f32| a + b)
    };

    let subtract = Operator {
        precedence: 4,
        func: Box::new(move |a: f32, b:f32| a - b)
    };

    let mut operators = HashMap::new();

    operators.insert('*', multiply);
    operators.insert('/', divide);
    operators.insert('+', add);
    operators.insert('-', subtract);

    operators
}

fn main () {
    let args: Vec<_> = env::args().collect();
    let tokens: Vec<&str> = args[1].split(" ").collect();
    let mut operator_stack: Vec<char> = vec![];
    let mut output: Vec<String> = vec![];
    let operators = get_operators();

    for token in tokens {
        let maybe_int = token.parse::<i32>();

        match maybe_int {
            Ok(_) => output.push(token.to_string()),
            Err(_) => {
                if let Some(o1_char) = token.chars().last() {
                    if let Some(o1) = operators.get(&o1_char) {
                        while !operator_stack.is_empty() {
                            if let Some(o2_char) = operator_stack.pop() {
                                if let Some(o2) = operators.get(&o2_char) {
                                    if o1.precedence >= o2.precedence {
                                        output.push(o2_char.to_string());
                                    } else {
                                        operator_stack.push(o2_char);
                                        break;
                                    }
                                }
                            }
                        }

                        operator_stack.push(o1_char);
                    }
                }
            }
        }
    }

    while !operator_stack.is_empty() {
        let op = operator_stack.pop().unwrap().to_string();
        output.push(op);
    }

    println!("{:?}", output);
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate nalgebra;
extern crate riscan_pro;
extern crate rustc_serialize;

use docopt::Docopt;
use nalgebra::{Iterable, Transpose};
use riscan_pro::{Matrix, Project, ScanPosition};
use rustc_serialize::json::{Json, ToJson};
use std::collections::HashMap;

const USAGE: &'static str = "
RiSCAN PRO utilities.

Usage:
    riscan-pro export-filters <project> [<scan-position>]
    riscan-pro socs-to-glcs <project> [<scan-position>] [<x> <y> <z>]
    riscan-pro scan-positions <project>
    riscan-pro tpl-glcs <project>
    riscan-pro (-h | --help)

Options:
    -h --help                       Show this screen.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_export_filters: bool,
    cmd_socs_to_glcs: bool,
    cmd_scan_positions: bool,
    cmd_tpl_glcs: bool,
    arg_project: String,
    arg_scan_position: Option<String>,
    arg_x: Option<f64>,
    arg_y: Option<f64>,
    arg_z: Option<f64>,
}

fn main() {
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit());
    if args.cmd_socs_to_glcs {
        let scan_position = if let Some(scan_position) = args.arg_scan_position {
            let project = Project::from_path(args.arg_project).unwrap();
            project.scan_position(&scan_position).unwrap().clone()
        } else {
            ScanPosition::from_path(args.arg_project).unwrap()
        };
        let glcs = scan_position.socs_to_glcs((args.arg_x.unwrap_or(0.),
                                               args.arg_y.unwrap_or(0.),
                                               args.arg_z.unwrap_or(0.)));
        println!("{:.2}, {:.2}, {:.2}", glcs.0, glcs.1, glcs.2);
    } else if args.cmd_scan_positions {
        let project = Project::from_path(args.arg_project).unwrap();
        for scan_position in project.scan_positions() {
            let glcs = scan_position.socs_to_glcs((0., 0., 0.));
            println!("{} {:.2} {:.2}", scan_position.name(), glcs.0, glcs.1);
        }
    } else if args.cmd_tpl_glcs {
        let project = Project::from_path(args.arg_project).unwrap();
        for tiepoint in project.tpl_glcs() {
            println!("{} {:.2} {:.2}", tiepoint.name, tiepoint.x, tiepoint.y);
        }
    } else if args.cmd_export_filters {
        let scan_position = if let Some(scan_position) = args.arg_scan_position {
            let project = Project::from_path(args.arg_project).unwrap();
            project.scan_position(&scan_position).unwrap().clone()
        } else {
            ScanPosition::from_path(args.arg_project).unwrap()
        };
        let mut filters = Vec::new();
        filters.push(filters_transformation(scan_position.sop()));
        filters.push(filters_transformation(scan_position.pop()));
        println!("{}", filters.to_json());
    }
}

fn filters_transformation(matrix: Matrix) -> Json {
    let mut filter = HashMap::new();
    filter.insert("type".to_string(), "filters.transformation".to_json());
    filter.insert("matrix".to_string(),
                  matrix.transpose()
                      .iter()
                      .map(|n| format!("{}", n))
                      .collect::<Vec<_>>()
                      .join(" ")
                      .to_json());
    filter.to_json()
}
<commit_msg>Replace spaces with commas<commit_after>extern crate docopt;
extern crate nalgebra;
extern crate riscan_pro;
extern crate rustc_serialize;

use docopt::Docopt;
use nalgebra::{Iterable, Transpose};
use riscan_pro::{Matrix, Project, ScanPosition};
use rustc_serialize::json::{Json, ToJson};
use std::collections::HashMap;

const USAGE: &'static str = "
RiSCAN PRO utilities.

Usage:
    riscan-pro export-filters <project> [<scan-position>]
    riscan-pro socs-to-glcs <project> [<scan-position>] [<x> <y> <z>]
    riscan-pro scan-positions <project>
    riscan-pro tpl-glcs <project>
    riscan-pro (-h | --help)

Options:
    -h --help                       Show this screen.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_export_filters: bool,
    cmd_socs_to_glcs: bool,
    cmd_scan_positions: bool,
    cmd_tpl_glcs: bool,
    arg_project: String,
    arg_scan_position: Option<String>,
    arg_x: Option<f64>,
    arg_y: Option<f64>,
    arg_z: Option<f64>,
}

fn main() {
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit());
    if args.cmd_socs_to_glcs {
        let scan_position = if let Some(scan_position) = args.arg_scan_position {
            let project = Project::from_path(args.arg_project).unwrap();
            project.scan_position(&scan_position).unwrap().clone()
        } else {
            ScanPosition::from_path(args.arg_project).unwrap()
        };
        let glcs = scan_position.socs_to_glcs((args.arg_x.unwrap_or(0.),
                                               args.arg_y.unwrap_or(0.),
                                               args.arg_z.unwrap_or(0.)));
        println!("{:.2},{:.2},{:.2}", glcs.0, glcs.1, glcs.2);
    } else if args.cmd_scan_positions {
        let project = Project::from_path(args.arg_project).unwrap();
        for scan_position in project.scan_positions() {
            let glcs = scan_position.socs_to_glcs((0., 0., 0.));
            println!("{},{:.2},{:.2}", scan_position.name(), glcs.0, glcs.1);
        }
    } else if args.cmd_tpl_glcs {
        let project = Project::from_path(args.arg_project).unwrap();
        for tiepoint in project.tpl_glcs() {
            println!("{},{:.2},{:.2}", tiepoint.name, tiepoint.x, tiepoint.y);
        }
    } else if args.cmd_export_filters {
        let scan_position = if let Some(scan_position) = args.arg_scan_position {
            let project = Project::from_path(args.arg_project).unwrap();
            project.scan_position(&scan_position).unwrap().clone()
        } else {
            ScanPosition::from_path(args.arg_project).unwrap()
        };
        let mut filters = Vec::new();
        filters.push(filters_transformation(scan_position.sop()));
        filters.push(filters_transformation(scan_position.pop()));
        println!("{}", filters.to_json());
    }
}

fn filters_transformation(matrix: Matrix) -> Json {
    let mut filter = HashMap::new();
    filter.insert("type".to_string(), "filters.transformation".to_json());
    filter.insert("matrix".to_string(),
                  matrix.transpose()
                      .iter()
                      .map(|n| format!("{}", n))
                      .collect::<Vec<_>>()
                      .join(" ")
                      .to_json());
    filter.to_json()
}
<|endoftext|>


<commit_before>extern crate libterminal_cribbage;

use libterminal_cribbage::cards::Deck;

fn main() {
    let mut d = Deck::new();

    for _ in 0..100000 {
        d = Deck::new();
    }
}
<commit_msg>Clean main of useless code.<commit_after>fn main() {
}
<|endoftext|>