<commit_before>extern crate yaml_rust;
extern crate regex;

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;

#[derive(Copy, Clone)]
struct App {
  print_ascii: bool,
  print_binary: 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 mut app = App { print_ascii: false, print_binary: 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 Requst", r"^\x10\x01\x00.\x00\x00")
  ];
  let io_timeout = Duration::new(300, 0); // 5 minutes

  let mut file = File::open("config.yml").unwrap();
  let mut config_str = String::new();
  file.read_to_string(&mut config_str).unwrap();
  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");
    }
  }
  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();

  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);
          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>Add binary matches for SOCKS5<commit_after>extern crate yaml_rust;
extern crate regex;

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;

#[derive(Copy, Clone)]
struct App {
  print_ascii: bool,
  print_binary: 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 mut app = App { print_ascii: false, print_binary: 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"),
    ("SOCKS5 NOAUTH Request", r"^\x05\x01\x00$"),
    ("SOCKS5 NOAUTH,USER/PASS Request", r"^\x05\x02\x00\x02$")
  ];
  let io_timeout = Duration::new(300, 0); // 5 minutes

  let mut file = File::open("config.yml").unwrap();
  let mut config_str = String::new();
  file.read_to_string(&mut config_str).unwrap();
  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");
    }
  }
  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();

  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);
          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>extern crate bindgen;
#[macro_use]
extern crate log;
extern crate docopt;
#[macro_use]
extern crate rustc_serialize;
extern crate env_logger;

use bindgen::{Builder, LinkType, Logger};
use std::io::{self, Write};
use std::fs::File;
use std::process::exit;

#[derive(Debug)]
struct StdLogger;

impl Logger for StdLogger {
    fn error(&self, msg: &str) {
        error!("{}", msg);
    }

    fn warn(&self, msg: &str) {
        warn!("{}", msg);
    }
}

const USAGE: &'static str = "
Generate C bindings for Rust.

Usage:
  bindgen [options] <file>
  bindgen (-h | --help)

Options:
  -h, --help                   Display this help message.
  --link=<library>             Link to a dynamic library, can be provided multiple times.
                               <library> is in the format `[kind=]lib`, where `kind` is
                               one of `static`, `dynamic` or `framework`.
  --output=<output>            Write bindings to <output> (- is stdout).
                               [default: -]
  --match=<name>               Only output bindings for definitions from files
                               whose name contains <name>
                               If multiple -match options are provided, files
                               matching any rule are bound to.
  --builtins                   Output bindings for builtin definitions
                               (for example __builtin_va_list)
  --emit-clang-ast             Output the ast (for debugging purposes)
  --override-enum-type=<type>  Override enum type, type name could be
                                 uchar
                                 schar
                                 ushort
                                 sshort
                                 uint
                                 sint
                                 ulong
                                 slong
                                 ulonglong
                                 slonglong
  --use-core                  Use `core` as a base crate for `Option` and such.
                              See also `--ctypes-prefix`.
  --ctypes-prefix=<prefix>    Use this prefix for all the types in the generated
                              code.
                              [default: std::os::raw]
  --clang-options=<opts>      Options to clang.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_file: String,
    flag_link: String,
    flag_output: String,
    flag_match: Option<String>,
    flag_builtins: bool,
    flag_emit_clang_ast: bool,
    flag_override_enum_type: String,
    flag_clang_options: String,
    flag_ctypes_prefix: String,
    flag_use_core: bool,
}

fn args_to_opts(args: Args, builder: &mut Builder) {
    builder.header(args.arg_file)
           .emit_ast(args.flag_emit_clang_ast)
           .ctypes_prefix(args.flag_ctypes_prefix
                              .split("::")
                              .map(String::from)
                              .collect::<Vec<_>>())
           .use_core(args.flag_use_core)
           .override_enum_ty(args.flag_override_enum_type);
    for arg in args.flag_clang_options.split(" ") {
        builder.clang_arg(arg);
    }
    if let Some(s) = args.flag_match {
        builder.match_pat(s);
    }
    if args.flag_builtins {
        builder.builtins();
    }
    let mut parts = args.flag_link.split('=');
    let (lib, kind) = match (parts.next(), parts.next()) {
        (Some(lib), None) => (lib, LinkType::Dynamic),
        (Some(kind), Some(lib)) => {
            (lib,
             match kind {
                "static" => LinkType::Static,
                "dynamic" => LinkType::Dynamic,
                "framework" => LinkType::Framework,
                _ => {
                    println!("Link type unknown: {}", kind);
                    exit(1);
                }
            })
        }
        _ => {
            println!("Wrong link format: {}", args.flag_link);
            exit(1);
        }
    };
    builder.link(lib, kind);
}

fn get_output(o: &str) -> Box<Write> {
    if o == "-" {
        Box::new(io::stdout())
    } else {
        Box::new(File::open(o).expect(&format!("\"{}\" unreadable", o)))
    }
}

pub fn main() {
    env_logger::init().unwrap();

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

    let output = get_output(&args.flag_output);

    let logger = StdLogger;
    let mut builder = Builder::default();
    builder.log(&logger);
    args_to_opts(args, &mut builder);
    debug!("{:?}", builder);

    match builder.generate() {
        Ok(bindings) => {
            match bindings.write(output) {
                Ok(()) => (),
                Err(e) => {
                    logger.error(&format!("Unable to write bindings to file. {}", e)[..]);
                    exit(-1);
                }
            }
        }
        Err(()) => exit(-1),
    }
}
<commit_msg>[main] Better clang args handling.<commit_after>extern crate bindgen;
#[macro_use]
extern crate log;
extern crate docopt;
#[macro_use]
extern crate rustc_serialize;
extern crate env_logger;

use bindgen::{Builder, LinkType, Logger};
use std::io::{self, Write};
use std::fs::File;
use std::process::exit;

#[derive(Debug)]
struct StdLogger;

impl Logger for StdLogger {
    fn error(&self, msg: &str) {
        error!("{}", msg);
    }

    fn warn(&self, msg: &str) {
        warn!("{}", msg);
    }
}

const USAGE: &'static str = "
Generate C bindings for Rust.

Usage:
  bindgen [options] <file> [-- <clang-args>...]
  bindgen (-h | --help)

Options:
  <clang-args>                 Options passed directly to clang.
  -h, --help                   Display this help message.
  --link=<library>             Link to a dynamic library, can be provided multiple times.
                               <library> is in the format `[kind=]lib`, where `kind` is
                               one of `static`, `dynamic` or `framework`.
  --output=<output>            Write bindings to <output> (- is stdout).
                               [default: -]
  --match=<name>               Only output bindings for definitions from files
                               whose name contains <name>
                               If multiple -match options are provided, files
                               matching any rule are bound to.
  --builtins                   Output bindings for builtin definitions
                               (for example __builtin_va_list)
  --emit-clang-ast             Output the ast (for debugging purposes)
  --override-enum-type=<type>  Override enum type, type name could be
                                 uchar
                                 schar
                                 ushort
                                 sshort
                                 uint
                                 sint
                                 ulong
                                 slong
                                 ulonglong
                                 slonglong
  --use-core                  Use `core` as a base crate for `Option` and such.
                              See also `--ctypes-prefix`.
  --ctypes-prefix=<prefix>    Use this prefix for all the types in the generated
                              code.
                              [default: std::os::raw]
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_file: String,
    arg_clang_args: Vec<String>,
    flag_link: String,
    flag_output: String,
    flag_match: Option<String>,
    flag_builtins: bool,
    flag_emit_clang_ast: bool,
    flag_override_enum_type: String,
    flag_ctypes_prefix: String,
    flag_use_core: bool,
}

fn args_to_opts(args: Args, builder: &mut Builder) {
    builder.header(args.arg_file)
           .emit_ast(args.flag_emit_clang_ast)
           .ctypes_prefix(args.flag_ctypes_prefix
                              .split("::")
                              .map(String::from)
                              .collect::<Vec<_>>())
           .use_core(args.flag_use_core)
           .override_enum_ty(args.flag_override_enum_type);
    for arg in args.arg_clang_args {
        builder.clang_arg(arg);
    }
    if let Some(s) = args.flag_match {
        builder.match_pat(s);
    }
    if args.flag_builtins {
        builder.builtins();
    }
    let mut parts = args.flag_link.split('=');
    let (lib, kind) = match (parts.next(), parts.next()) {
        (Some(lib), None) => (lib, LinkType::Dynamic),
        (Some(kind), Some(lib)) => {
            (lib,
             match kind {
                "static" => LinkType::Static,
                "dynamic" => LinkType::Dynamic,
                "framework" => LinkType::Framework,
                _ => {
                    println!("Link type unknown: {}", kind);
                    exit(1);
                }
            })
        }
        _ => {
            println!("Wrong link format: {}", args.flag_link);
            exit(1);
        }
    };
    builder.link(lib, kind);
}

fn get_output(o: &str) -> Box<Write> {
    if o == "-" {
        Box::new(io::stdout())
    } else {
        Box::new(File::open(o).expect(&format!("\"{}\" unreadable", o)))
    }
}

pub fn main() {
    env_logger::init().unwrap();

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

    let output = get_output(&args.flag_output);

    let logger = StdLogger;
    let mut builder = Builder::default();
    builder.log(&logger);
    args_to_opts(args, &mut builder);
    debug!("{:?}", builder);

    match builder.generate() {
        Ok(bindings) => {
            match bindings.write(output) {
                Ok(()) => (),
                Err(e) => {
                    logger.error(&format!("Unable to write bindings to file. {}", e)[..]);
                    exit(-1);
                }
            }
        }
        Err(()) => exit(-1),
    }
}
<|endoftext|>


<commit_before>struct Item(&'static str);

struct Location {
    description: &'static str,
    items: Vec<Item>,
}

fn main() {
    let item1 = Item("Little key");
    let item2 = Item("Big key");
    let hall = Location{ description: "A wide open space. Streams of lava flow on both sides of the entry gate.",
                         items: vec![item1, item2] };
}
<commit_msg>Considering some use cases for actions.<commit_after>struct Item(&'static str);

struct Location {
    description: &'static str,
    items: Vec<Item>,
}

// how to do actions?
// as an enum? sounds reasonable.
// what properties do they have?
// a keyword which is typed in
// one or more arguments, possibly a variable number
// something which happens when they are invoked

// "look": print the area description
// "take + item": move the item to the player's inventory
// "go + direction": move to the area in that direction
// "use + item (+ object)": maybe remove the item, invoke a (targeted?) effect

fn main() {
    let item1 = Item("Little key");
    let item2 = Item("Big key");
    let hall = Location{ description: "A wide open space. Streams of lava flow on both sides of the entry gate.",
                         items: vec![item1, item2] };
}
<|endoftext|>


<commit_before>use std::env;
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));
}

fn build_config() -> Result<Config, 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");

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

    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_ref().map(|string| string.as_str()),
        work_mode,
        matches.opt_str("d").as_ref().map(|string| string.as_str()),
        matches.free.get(0).as_ref().map(|string| string.as_str()),
        matches.free.get(1).as_ref().map(|string| string.as_str()),
        matches.opt_str("o").as_ref().map(|string| string.as_str()),
        matches
            .opt_str("doc-target-path")
            .as_ref()
            .map(|string| string.as_str()),
        matches.opt_present("b"),
        matches.opt_present("s"),
    )
}

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

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

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(cfg) => cfg,
        Err(err) => return Err(err),
    };

    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, &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("Analysing");
        gir::analysis_run(&mut env);
    }

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

    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>Factor as_str_ref()<commit_after>use std::env;
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())
    }
}

fn build_config() -> Result<Config, 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");

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

    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"),
    )
}

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

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

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(cfg) => cfg,
        Err(err) => return Err(err),
    };

    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, &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("Analysing");
        gir::analysis_run(&mut env);
    }

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

    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>#![cfg_attr(test, allow(dead_code))]

// TODO revisit these after 1.0.0beta
#![feature(env)]
#![feature(io)]
#![feature(path)]

extern crate shader_version;
extern crate input;
extern crate event;
extern crate graphics;
extern crate sdl2_window;
extern crate window;
extern crate opengl_graphics;
extern crate quack;

extern crate chip8_vm;

use std::cell::RefCell;
use sdl2_window::Sdl2Window;
use window::WindowSettings;
use opengl_graphics::{
    Gl,
};

use std::env;
use std::old_io::File;
use std::old_io::BufReader;
// use std::time::duration::Duration;
use quack::Set;
// use input::keyboard::Key;
use input::Button;

use chip8_vm::vm::Vm;

const TITLE: &'static str = "Chip8";
const BEEP_TITLE: &'static str = "♬ Chip8 ♬";

const INTRO_ROM: &'static [u8] = include_bytes!("intro/intro.ch8");

fn main() {
    let mut vm = Vm::new();

    let mut rom: Option<File> = None;

    if let Some(rom_path) = env::args().skip(1).next() {
        if let Ok(f) = File::open(&Path::new(&rom_path)) {
            rom = Some(f);
        } else {
            println!("Could not open rom {}", rom_path);
        }
    }

    let intro_reader = &mut BufReader::new(INTRO_ROM) as &mut Reader;
    let mut rom_reader = match &mut rom {
        &mut Some(ref mut r) => r as &mut Reader,
        _ => {
            println!("You can provide a path to a chip8 binary to interpret it.");
            intro_reader
        }
    };

    match vm.load_rom(rom_reader) {
        Ok(size) => println!("Loaded rom size: {}", size),
        Err(e) => {
            println!("Error loading rom: {}", e);
            return;
        }
    }

    let (width, height) = (800, 400);
    let opengl = shader_version::OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        WindowSettings {
            title: TITLE.to_string(),
            size: [width, height],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let ref mut gl = Gl::new(opengl);
    let window = RefCell::new(window);

    fn keymap(k: Option<Button>) -> Option<u8> {
        use input::Key::*;
        if let Some(Button::Keyboard(k)) = k {
            return match k {
                D1 => Some(0x1),
                D2 => Some(0x2),
                D3 => Some(0x3),

                Q  => Some(0x4),
                W  => Some(0x5),
                E  => Some(0x6),

                A  => Some(0x7),
                S  => Some(0x8),
                D  => Some(0x9),

                Z  => Some(0xA),
                X  => Some(0x0),
                C  => Some(0xB),

                D4 => Some(0xC),
                R  => Some(0xD),
                F  => Some(0xE),
                V  => Some(0xF),

                _ => None
            }
        }
        return None
    }

    for e in event::events(&window) {
        use event::{ ReleaseEvent, UpdateEvent, PressEvent, RenderEvent };

        if let Some(args) = e.update_args() {
            vm.step(args.dt as f32);
            if vm.beeping() {
                (*window.borrow_mut()).window.set_title(BEEP_TITLE);
            } else {
                (*window.borrow_mut()).window.set_title(TITLE);
            }
        }
        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([0.0, 0.0, 0.0, 1.0], gl);
                let r = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
                let off = Color([0.0, 0.0, 0.0, 1.0]);
                let on = Color([1.0, 1.0, 1.0, 1.0]);

                let w = args.width as f64 / 64.0;
                let h = args.height as f64 / 32.0;

                for (y,row) in vm.screen_rows().enumerate() {
                    for (x,byte) in row.iter().enumerate() {
                        let x = x as f64 * w;
                        let y = y as f64 * h;
                        r.set(match *byte { 0 => off, _ => on })
                        .draw([x, y, w, h], &c, gl);
                    }
                }
            });
        }
        if let Some(keynum) = keymap(e.press_args()) {
            vm.set_key(keynum);
        }
        if let Some(keynum) = keymap(e.release_args()) {
            vm.unset_key(keynum);
        }
    }
}
<commit_msg>Use new `std::io` module<commit_after>#![cfg_attr(test, allow(dead_code))]

// TODO revisit these after 1.0.0beta
#![feature(env)]
#![feature(io)]
#![feature(path)]
#![feature(os)]
#![feature(fs)]

extern crate shader_version;
extern crate input;
extern crate event;
extern crate graphics;
extern crate sdl2_window;
extern crate window;
extern crate opengl_graphics;
extern crate quack;

extern crate chip8_vm;

use std::cell::RefCell;
use sdl2_window::Sdl2Window;
use window::WindowSettings;
use opengl_graphics::{
    Gl,
};

use std::env;
use std::io::{Read, BufReader};
use std::fs::File;
// use std::time::duration::Duration;
use quack::Set;
// use input::keyboard::Key;
use input::Button;

use chip8_vm::vm::Vm;

const TITLE: &'static str = "Chip8";
const BEEP_TITLE: &'static str = "♬ Chip8 ♬";

const INTRO_ROM: &'static [u8] = include_bytes!("intro/intro.ch8");

fn main() {
    let mut vm = Vm::new();

    let mut rom: Option<File> = None;

    if let Some(rom_path) = env::args().skip(1).next() {
        if let Ok(f) = File::open(&Path::new(&rom_path)) {
            rom = Some(f);
        } else {
            println!("Could not open rom {}", rom_path);
        }
    }

    let intro_reader = &mut BufReader::new(INTRO_ROM) as &mut Read;
    let mut rom_reader = match &mut rom {
        &mut Some(ref mut r) => r as &mut Read,
        _ => {
            println!("You can provide a path to a chip8 binary to interpret it.");
            intro_reader
        }
    };

    match vm.load_rom(rom_reader) {
        Ok(size) => println!("Loaded rom size: {}", size),
        Err(e) => {
            println!("Error loading rom: {}", e);
            return;
        }
    }

    let (width, height) = (800, 400);
    let opengl = shader_version::OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        WindowSettings {
            title: TITLE.to_string(),
            size: [width, height],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let ref mut gl = Gl::new(opengl);
    let window = RefCell::new(window);

    fn keymap(k: Option<Button>) -> Option<u8> {
        use input::Key::*;
        if let Some(Button::Keyboard(k)) = k {
            return match k {
                D1 => Some(0x1),
                D2 => Some(0x2),
                D3 => Some(0x3),

                Q  => Some(0x4),
                W  => Some(0x5),
                E  => Some(0x6),

                A  => Some(0x7),
                S  => Some(0x8),
                D  => Some(0x9),

                Z  => Some(0xA),
                X  => Some(0x0),
                C  => Some(0xB),

                D4 => Some(0xC),
                R  => Some(0xD),
                F  => Some(0xE),
                V  => Some(0xF),

                _ => None
            }
        }
        return None
    }

    for e in event::events(&window) {
        use event::{ ReleaseEvent, UpdateEvent, PressEvent, RenderEvent };

        if let Some(args) = e.update_args() {
            vm.step(args.dt as f32);
            if vm.beeping() {
                (*window.borrow_mut()).window.set_title(BEEP_TITLE);
            } else {
                (*window.borrow_mut()).window.set_title(TITLE);
            }
        }
        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([0.0, 0.0, 0.0, 1.0], gl);
                let r = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
                let off = Color([0.0, 0.0, 0.0, 1.0]);
                let on = Color([1.0, 1.0, 1.0, 1.0]);

                let w = args.width as f64 / 64.0;
                let h = args.height as f64 / 32.0;

                for (y,row) in vm.screen_rows().enumerate() {
                    for (x,byte) in row.iter().enumerate() {
                        let x = x as f64 * w;
                        let y = y as f64 * h;
                        r.set(match *byte { 0 => off, _ => on })
                        .draw([x, y, w, h], &c, gl);
                    }
                }
            });
        }
        if let Some(keynum) = keymap(e.press_args()) {
            vm.set_key(keynum);
        }
        if let Some(keynum) = keymap(e.release_args()) {
            vm.unset_key(keynum);
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serenity;
extern crate rand;
extern crate typemap;
extern crate stalch;
extern crate seximal;

use std::io;
use stalch::{run_with_state, InOuter, State, Result as StalchResult};

use std::env;
use std::result::Result as StdResult;
use typemap::Key;

use rand::Rng;
use rand::thread_rng;

use serenity::prelude::*;
use serenity::model::*;
use serenity::Result;
use serenity::utils;

use serenity::framework::StandardFramework;

const PREFIX: &str = "f>";

command!(info(_ctx, msg, _args) {
    msg.channel_id.send_message(|cm| {
        cm.embed(|e| {
            e.title("lfalchbot")
             .colour(utils::Colour::blue())
             .description("(c) LFalch.com 2017")
             .footer(|f| f.text(serenity::constants::USER_AGENT))
        })
    }).unwrap();
});

command!(setgame(ctx, _msg, args) {
    ctx.set_game(Game::playing(&args.join(" ")));
});

command!(rpn(_ctx, msg, args) {
    match calculate(&*args) {
        Ok(r) => msg.reply(&format!("Result: {}", r)),
        Err(e) => msg.reply(&format!("Error: {:?}", e))
    }.unwrap();
});

command!(stalch(_ctx, msg, args) {
    match stalch_run(args.join(" ") + "\n") {
        Ok((r, s)) => {
            if r.is_empty() {
                msg.reply(&format!("Stack:\n```\n{}\n```", s))
            } else {
                msg.reply(&format!("Output:\n```\n{}\n```", r))
            }
        }
        Err(e) => msg.reply(&format!("Error: {:?}", e))
    }.unwrap();
});

command!(seximal(_ctx, msg, args) {
    let s = args.join("");
    match seximal::to_seximal_words(&s) {
        Ok(ref s) => msg.reply(s),
        Err(_) => msg.reply("Malformed number")
    }.unwrap();
});

const CSGO_MSGS: [&str; 6] = [
    "Vi varmer op med en comp!",
    "Jeg er på!",
    "Jeg er mere til Call of Duty ..",
    "Сука блядь!",
    "-skyder en bot for at få dens Bizon-",
    "Mongoskrald!"
];

const BEARTOOTH: [&str; 3] = [
    "I’m not useless! I’m just the king of excuses!",
    "One life and one decision! Make sure it ends with you still living!",
    "Lorteskat på T-shirts."
];

const RESPONSES: [&str; 4] = [
    "Undskyld, kan ikke snakke lige nu :(",
    "Hey, kan jeg ringe igen senere?",
    "Hva' så, din noob!? :P",
    "Ad, hvem er du?"
];

const REDALERT: [&str; 4] = [
    "Your base is under a salt!",
    "Det gamle lortespil?",
    "Jeg er mere til CSGO.",
    "\"Mine depleted\" ..."
];

struct BotUser;

impl Key for BotUser {
    type Value = String;
}

struct Handler;

fn main() {
    let token = env::var("DISCORD_TOKEN")
        .expect("Expected a token in the environment");
    let mut client = Client::new(&token, Handler);

    client.with_framework(StandardFramework::new()
        .configure(|c| c.prefix(PREFIX))
        .command("ping", |c| c.exec_str("Pong!"))
        .on("info", info)
        .on("setgame", setgame)
        .on("rpn", rpn)
        .on("stalch", stalch)
        .on("seximal", seximal)
    );

    {
        let mut data = client.data.lock();
        data.insert::<BotUser>(String::default());
    }

    if let Err(why) = client.start() {
        println!("Client error: {:?}", why);
    }
}

macro_rules! joke {
    ($s:expr; $($trigger:expr),+; $bl:block) => (
        if $($s.contains($trigger))||* $bl
    );
    ($s:expr, $channel_id:expr; $($trigger:expr),+;; $joke:expr) => (
        joke!($s; $($trigger),*; {
            $channel_id.say($joke).unwrap();
        })
    );
    ($s:expr, $channel_id:expr; $($trigger:expr),+; $jokes:expr) => (
        joke!($s; $($trigger),*; {
            send_random($channel_id, &$jokes).unwrap();
        })
    );
}

impl EventHandler for Handler {
    fn on_ready(&self, ctx: Context, ready: Ready) {
        println!("{} is connected!", ready.user.name);
        println!("Guilds:");
        for name in ready.guilds.iter().map(|g| g.id().get().unwrap().name) {
            println!("    {}", name);
        }
        {
            let mut data = ctx.data.lock();
            *data.get_mut::<BotUser>().unwrap() = ready.user.tag();
        }
    }

    fn on_message(&self, ctx: Context, msg: Message) {
        if msg.author.bot {
            return
        }
        let s: String = msg.content.chars()
        .filter(|c| c.is_alphanumeric())
        .flat_map(|c|c.to_lowercase())
        .collect();

        joke!(s, msg.channel_id; "css", "source";; "Hvor er mine skins!?");
        joke!(s, msg.channel_id; "csgo", "counterstrike", "globaloffensive"; CSGO_MSGS);
        joke!(s, msg.channel_id; "mc", "minecraft";; "MINECRAFT!");
        joke!(s, msg.channel_id; "beartooth"; BEARTOOTH);
        joke!(s, msg.channel_id; "rep";; "Rep mig!");
        joke!(s, msg.channel_id; "ftl";; "Zoltan shield OP");
        joke!(s, msg.channel_id; "bindingofisaac";; "Mom OP");
        joke!(s, msg.channel_id; "meme";; "krydrede migmig'er");
        joke!(s, msg.channel_id; "gunsoficarus";; "Spillere online: 85");
        joke!(s, msg.channel_id; "doom";; "Rip and tear!");
        joke!(s, msg.channel_id; "dyinglight";; "Det dér Left 4 Dead-spil?");
        joke!(s, msg.channel_id; "report";; "ReviewBrah");
        joke!(s; "english"; {
            msg.channel_id.send_message(|cm| {
                cm.embed(|e| {
                    e.image("http://dev.lfalch.com/english.jpg")
                })
            }).unwrap();
        });
        joke!(s, msg.channel_id; "warthunder", "wt", "thunder", "tankspil";; "Jeg hader World of Tanks!");
        joke!(s, msg.channel_id; "ra3", "redalert"; REDALERT);
        joke!(s, msg.channel_id; "rusland", "russia", "росси", "russisk",
        "russian", "русск", "russer";; "Communism is the ultimate goal of socialism.");

        let user = {
            ctx.data.lock().get::<BotUser>().unwrap().clone()
        };
        if msg.mentions.iter().map(|u| u.tag()).any(|u| u == user) {
            send_random(msg.channel_id, &RESPONSES).unwrap();
        }
    }
}

fn send_random(chl: ChannelId, list: &[&str]) -> Result<Message> {
    let i = thread_rng().gen_range(0, list.len());
    chl.say(list[i])
}

#[derive(Debug, Copy, Clone)]
pub enum RpnError<'a> {
    StackTooSmall,
    UnknownOperator(&'a str)
}

use RpnError::*;

pub fn calculate<'a, T: IntoIterator<Item=&'a String>>(operations: T) -> StdResult<f64, RpnError<'a>> {
    let mut stack = Vec::new();

    for operation in operations {
        if let Some(d) = operation.parse::<f64>().ok() {
            stack.push(d)
        }else{
            calc(operation, &mut stack)?
        }
    }

    stack.pop().ok_or(StackTooSmall)
}

fn calc<'a>(op: &'a str, stack: &mut Vec<f64>) -> StdResult<(), RpnError<'a>>{
    let res = match (stack.pop(), stack.pop()){
        (Some(op1), Some(op2)) => match op{
            "+"|"add" => op2 + op1,
            "-"|"sub" => op2 - op1,
            "/"|"div" => op2 / op1,
            "*"|"mul" => op2 * op1,
            "^"|"pow" => op2.powf(op1),
            "log" => op2.log(op1),
            "hypot" => op2.hypot(op1),
            "%"|"rem" => op2 % op1,
            "|"|"or" => (op2 as i64 | op1 as i64) as f64,
            "&"|"and" => (op2 as i64 & op1 as i64) as f64,
            "xor" => (op2  as i64 ^ op1 as i64) as f64,
            _ => return Err(UnknownOperator(op))
        },
        _ => return Err(StackTooSmall)
    };
    Ok(stack.push(res))
}

fn stalch_run<'a>(s: String) -> StalchResult<(String, String)> {
    let mut state = State::new();
    let mut io = InOuter::new(Vec::new(), io::repeat(b'\n'));

    run_with_state(s.as_bytes(), &mut state, &mut io)?;

    let (output, _) = io.extract();

    let s = String::from_utf8(output).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;

    Ok((s, format!("{:?}", state.stack())))
}
<commit_msg>Add good joke<commit_after>#[macro_use]
extern crate serenity;
extern crate rand;
extern crate typemap;
extern crate stalch;
extern crate seximal;

use std::io;
use stalch::{run_with_state, InOuter, State, Result as StalchResult};

use std::env;
use std::result::Result as StdResult;
use typemap::Key;

use rand::Rng;
use rand::thread_rng;

use serenity::prelude::*;
use serenity::model::*;
use serenity::Result;
use serenity::utils;

use serenity::framework::StandardFramework;

const PREFIX: &str = "f>";
const WESTMANN: UserId = UserId(229154015626264577);
const MEMES: ChannelId = ChannelId(306454829738491904);

command!(info(_ctx, msg, _args) {
    msg.channel_id.send_message(|cm| {
        cm.embed(|e| {
            e.title("lfalchbot")
             .colour(utils::Colour::blue())
             .description("(c) LFalch.com 2017")
             .footer(|f| f.text(serenity::constants::USER_AGENT))
        })
    }).unwrap();
});

command!(setgame(ctx, _msg, args) {
    ctx.set_game(Game::playing(&args.join(" ")));
});

command!(rpn(_ctx, msg, args) {
    match calculate(&*args) {
        Ok(r) => msg.reply(&format!("Result: {}", r)),
        Err(e) => msg.reply(&format!("Error: {:?}", e))
    }.unwrap();
});

command!(stalch(_ctx, msg, args) {
    match stalch_run(args.join(" ") + "\n") {
        Ok((r, s)) => {
            if r.is_empty() {
                msg.reply(&format!("Stack:\n```\n{}\n```", s))
            } else {
                msg.reply(&format!("Output:\n```\n{}\n```", r))
            }
        }
        Err(e) => msg.reply(&format!("Error: {:?}", e))
    }.unwrap();
});

command!(seximal(_ctx, msg, args) {
    let s = args.join("");
    match seximal::to_seximal_words(&s) {
        Ok(ref s) => msg.reply(s),
        Err(_) => msg.reply("Malformed number")
    }.unwrap();
});

const CSGO_MSGS: [&str; 6] = [
    "Vi varmer op med en comp!",
    "Jeg er på!",
    "Jeg er mere til Call of Duty ..",
    "Сука блядь!",
    "-skyder en bot for at få dens Bizon-",
    "Mongoskrald!"
];

const BEARTOOTH: [&str; 3] = [
    "I’m not useless! I’m just the king of excuses!",
    "One life and one decision! Make sure it ends with you still living!",
    "Lorteskat på T-shirts."
];

const RESPONSES: [&str; 4] = [
    "Undskyld, kan ikke snakke lige nu :(",
    "Hey, kan jeg ringe igen senere?",
    "Hva' så, din noob!? :P",
    "Ad, hvem er du?"
];

const REDALERT: [&str; 4] = [
    "Your base is under a salt!",
    "Det gamle lortespil?",
    "Jeg er mere til CSGO.",
    "\"Mine depleted\" ..."
];

struct BotUser;

impl Key for BotUser {
    type Value = String;
}

struct Handler;

fn main() {
    let token = env::var("DISCORD_TOKEN")
        .expect("Expected a token in the environment");
    let mut client = Client::new(&token, Handler);

    client.with_framework(StandardFramework::new()
        .configure(|c| c.prefix(PREFIX))
        .command("ping", |c| c.exec_str("Pong!"))
        .on("info", info)
        .on("setgame", setgame)
        .on("rpn", rpn)
        .on("stalch", stalch)
        .on("seximal", seximal)
    );

    {
        let mut data = client.data.lock();
        data.insert::<BotUser>(String::default());
    }

    if let Err(why) = client.start() {
        println!("Client error: {:?}", why);
    }
}

macro_rules! joke {
    ($s:expr; $($trigger:expr),+; $bl:block) => (
        if $($s.contains($trigger))||* $bl
    );
    ($s:expr, $channel_id:expr; $($trigger:expr),+;; $joke:expr) => (
        joke!($s; $($trigger),*; {
            $channel_id.say($joke).unwrap();
        })
    );
    ($s:expr, $channel_id:expr; $($trigger:expr),+; $jokes:expr) => (
        joke!($s; $($trigger),*; {
            send_random($channel_id, &$jokes).unwrap();
        })
    );
}

impl EventHandler for Handler {
    fn on_ready(&self, ctx: Context, ready: Ready) {
        println!("{} is connected!", ready.user.name);
        println!("Guilds:");
        for name in ready.guilds.iter().map(|g| g.id().get().unwrap().name) {
            println!("    {}", name);
        }
        {
            let mut data = ctx.data.lock();
            *data.get_mut::<BotUser>().unwrap() = ready.user.tag();
        }
    }

    fn on_message(&self, ctx: Context, msg: Message) {
        if msg.author.bot {
            return
        }
        if msg.channel_id == MEMES && msg.author.id = WESTMANN && msg.embeds.iter().any(|a| a.image.is_some()) {
            msg.channel_id.say("Den er gammel!");
        }
        let s: String = msg.content.chars()
        .filter(|c| c.is_alphanumeric())
        .flat_map(|c|c.to_lowercase())
        .collect();

        joke!(s, msg.channel_id; "css", "source";; "Hvor er mine skins!?");
        joke!(s, msg.channel_id; "csgo", "counterstrike", "globaloffensive"; CSGO_MSGS);
        joke!(s, msg.channel_id; "mc", "minecraft";; "MINECRAFT!");
        joke!(s, msg.channel_id; "beartooth"; BEARTOOTH);
        joke!(s, msg.channel_id; "rep";; "Rep mig!");
        joke!(s, msg.channel_id; "ftl";; "Zoltan shield OP");
        joke!(s, msg.channel_id; "bindingofisaac";; "Mom OP");
        joke!(s, msg.channel_id; "meme";; "krydrede migmig'er");
        joke!(s, msg.channel_id; "gunsoficarus";; "Spillere online: 85");
        joke!(s, msg.channel_id; "doom";; "Rip and tear!");
        joke!(s, msg.channel_id; "dyinglight";; "Det dér Left 4 Dead-spil?");
        joke!(s, msg.channel_id; "report";; "ReviewBrah");
        joke!(s; "english"; {
            msg.channel_id.send_message(|cm| {
                cm.embed(|e| {
                    e.image("http://dev.lfalch.com/english.jpg")
                })
            }).unwrap();
        });
        joke!(s, msg.channel_id; "warthunder", "wt", "thunder", "tankspil";; "Jeg hader World of Tanks!");
        joke!(s, msg.channel_id; "ra3", "redalert"; REDALERT);
        joke!(s, msg.channel_id; "rusland", "russia", "росси", "russisk",
        "russian", "русск", "russer";; "Communism is the ultimate goal of socialism.");

        let user = {
            ctx.data.lock().get::<BotUser>().unwrap().clone()
        };
        if msg.mentions.iter().map(|u| u.tag()).any(|u| u == user) {
            send_random(msg.channel_id, &RESPONSES).unwrap();
        }
    }
}

fn send_random(chl: ChannelId, list: &[&str]) -> Result<Message> {
    let i = thread_rng().gen_range(0, list.len());
    chl.say(list[i])
}

#[derive(Debug, Copy, Clone)]
pub enum RpnError<'a> {
    StackTooSmall,
    UnknownOperator(&'a str)
}

use RpnError::*;

pub fn calculate<'a, T: IntoIterator<Item=&'a String>>(operations: T) -> StdResult<f64, RpnError<'a>> {
    let mut stack = Vec::new();

    for operation in operations {
        if let Some(d) = operation.parse::<f64>().ok() {
            stack.push(d)
        }else{
            calc(operation, &mut stack)?
        }
    }

    stack.pop().ok_or(StackTooSmall)
}

fn calc<'a>(op: &'a str, stack: &mut Vec<f64>) -> StdResult<(), RpnError<'a>>{
    let res = match (stack.pop(), stack.pop()){
        (Some(op1), Some(op2)) => match op{
            "+"|"add" => op2 + op1,
            "-"|"sub" => op2 - op1,
            "/"|"div" => op2 / op1,
            "*"|"mul" => op2 * op1,
            "^"|"pow" => op2.powf(op1),
            "log" => op2.log(op1),
            "hypot" => op2.hypot(op1),
            "%"|"rem" => op2 % op1,
            "|"|"or" => (op2 as i64 | op1 as i64) as f64,
            "&"|"and" => (op2 as i64 & op1 as i64) as f64,
            "xor" => (op2  as i64 ^ op1 as i64) as f64,
            _ => return Err(UnknownOperator(op))
        },
        _ => return Err(StackTooSmall)
    };
    Ok(stack.push(res))
}

fn stalch_run<'a>(s: String) -> StalchResult<(String, String)> {
    let mut state = State::new();
    let mut io = InOuter::new(Vec::new(), io::repeat(b'\n'));

    run_with_state(s.as_bytes(), &mut state, &mut io)?;

    let (output, _) = io.extract();

    let s = String::from_utf8(output).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;

    Ok((s, format!("{:?}", state.stack())))
}
<|endoftext|>


<commit_before>extern crate irc;
extern crate shlex;
extern crate getopts;

mod sh;

use std::io::{self, BufRead, BufReader};
use std::fs::File;
use std::thread;
use std::sync::mpsc::{channel, Sender};
use std::collections::HashMap;
use irc::client::data::command::Command;
use irc::client::data::message::Message;
use irc::client::server::{IrcServer, Server};
use irc::client::server::utils::ServerExt;
use getopts::Options;
use sh::{Sh, CmdFn};

const LEADER: char = '~';

fn join_start_channels<S>(server: &S) -> io::Result<()>
        where S: Server {
    let channels = BufReader::new(try!(File::open("channels.txt")));
    for line in channels.lines() {
        try!(server.send_join(&*try!(line)));
    }
    Ok(())
}

macro_rules! ignore {
    ($expression:expr) => (
        match $expression {
            Ok(()) => (),
            Err(..) => return,
        }
    )
}

macro_rules! send_fail {
    ($stderr:ident, $opts:ident, $argv:ident) => (
        match $opts.parse(&$argv[1..]) {
            Ok(m) => m,
            Err(f) => {
                ignore!($stderr.send(format!("{}: {}", $argv[0], f)));
                return
            },
        }
    )
}

static FLAGS: &'static CmdFn = &|argv, _, stdout, stderr| {
    let mut opts = Options::new();
    opts.optflag("t", "test", "test flag");
    let matches = send_fail!(stderr, opts, argv);
    ignore!(stdout.send(if matches.opt_present("t") {
        "test"
    } else {
        "not test"
    }.into()))
};

static ECHO: &'static CmdFn = &|mut argv, _, stdout, _| {
    ignore!(stdout.send(argv.split_off(1).join(" ")))
};

static CAT: &'static CmdFn = &|_, stdin, stdout, _| {
    for line in stdin.iter() {
        ignore!(stdout.send(line))
    }
};

static COUNT: &'static CmdFn = &|argv, stdin, stdout, _| {
    ignore!(stdout.send(format!("{}", if argv.len() == 1 {
        stdin.iter().count()
    } else {
        argv.len() - 1
    })))
};

fn find_or_spawn<'a, S>(server: &IrcServer,
                     user_senders: &'a mut HashMap<String, Sender<Message>>,
                     nick: S) -> &'a mut Sender<Message>
        where S: Into<String> {
    let nick = nick.into();
    user_senders.entry(nick.clone()).or_insert_with(|| {
        let (tx, rx) = channel::<Message>();
        let server = server.clone();
        thread::spawn(move || {
            let mut sh = Sh::new();
            sh.cmds.insert("flags", FLAGS);
            sh.cmds.insert("echo", ECHO);
            sh.cmds.insert("cat", CAT);
            sh.cmds.insert("count", COUNT);
            for message in rx.iter() {
                match message.command {
                    Command::PRIVMSG(ref target, ref msg) => {
                        let msg = msg.trim_left_matches(LEADER);
                        match sh.run_str(msg) {
                            Ok(rs) => {
                                server.send(Command::PRIVMSG(target.clone(),
                                    format!("{}> {}", nick, rs.join(" | ")))).unwrap();
                            },
                            Err(e) => {
                                server.send(Command::PRIVMSG(target.clone(),
                                    format!("{}! {}", nick, e))).unwrap();
                            }
                        }
                    },
                    _ => (),
                }
            }
        });
        tx
    })
}

fn main() {
    let server = IrcServer::new("config.json").unwrap();
    server.identify().unwrap();
    join_start_channels(&server).unwrap();
    let mut user_senders = HashMap::new();

    for message in server.iter() {
        let message = message.unwrap();
        match message.command {
            Command::PRIVMSG(_, ref msg) => {
                if msg.starts_with(LEADER) {
                    if let Some(chan) = message.source_nickname()
                            .map(|nick| find_or_spawn(&server,
                                                      &mut user_senders,
                                                      nick)) {
                        chan.send(message.clone()).unwrap();
                    }
                }
            },
            _ => (),
        }
    }
}
<commit_msg>Change the success sigil<commit_after>extern crate irc;
extern crate shlex;
extern crate getopts;

mod sh;

use std::io::{self, BufRead, BufReader};
use std::fs::File;
use std::thread;
use std::sync::mpsc::{channel, Sender};
use std::collections::HashMap;
use irc::client::data::command::Command;
use irc::client::data::message::Message;
use irc::client::server::{IrcServer, Server};
use irc::client::server::utils::ServerExt;
use getopts::Options;
use sh::{Sh, CmdFn};

const LEADER: char = '~';

fn join_start_channels<S>(server: &S) -> io::Result<()>
        where S: Server {
    let channels = BufReader::new(try!(File::open("channels.txt")));
    for line in channels.lines() {
        try!(server.send_join(&*try!(line)));
    }
    Ok(())
}

macro_rules! ignore {
    ($expression:expr) => (
        match $expression {
            Ok(()) => (),
            Err(..) => return,
        }
    )
}

macro_rules! send_fail {
    ($stderr:ident, $opts:ident, $argv:ident) => (
        match $opts.parse(&$argv[1..]) {
            Ok(m) => m,
            Err(f) => {
                ignore!($stderr.send(format!("{}: {}", $argv[0], f)));
                return
            },
        }
    )
}

static FLAGS: &'static CmdFn = &|argv, _, stdout, stderr| {
    let mut opts = Options::new();
    opts.optflag("t", "test", "test flag");
    let matches = send_fail!(stderr, opts, argv);
    ignore!(stdout.send(if matches.opt_present("t") {
        "test"
    } else {
        "not test"
    }.into()))
};

static ECHO: &'static CmdFn = &|mut argv, _, stdout, _| {
    ignore!(stdout.send(argv.split_off(1).join(" ")))
};

static CAT: &'static CmdFn = &|_, stdin, stdout, _| {
    for line in stdin.iter() {
        ignore!(stdout.send(line))
    }
};

static COUNT: &'static CmdFn = &|argv, stdin, stdout, _| {
    ignore!(stdout.send(format!("{}", if argv.len() == 1 {
        stdin.iter().count()
    } else {
        argv.len() - 1
    })))
};

fn find_or_spawn<'a, S>(server: &IrcServer,
                     user_senders: &'a mut HashMap<String, Sender<Message>>,
                     nick: S) -> &'a mut Sender<Message>
        where S: Into<String> {
    let nick = nick.into();
    user_senders.entry(nick.clone()).or_insert_with(|| {
        let (tx, rx) = channel::<Message>();
        let server = server.clone();
        thread::spawn(move || {
            let mut sh = Sh::new();
            sh.cmds.insert("flags", FLAGS);
            sh.cmds.insert("echo", ECHO);
            sh.cmds.insert("cat", CAT);
            sh.cmds.insert("count", COUNT);
            for message in rx.iter() {
                match message.command {
                    Command::PRIVMSG(ref target, ref msg) => {
                        let msg = msg.trim_left_matches(LEADER);
                        match sh.run_str(msg) {
                            Ok(rs) => {
                                server.send(Command::PRIVMSG(target.clone(),
                                    format!("{}$ {}", nick, rs.join(" | ")))).unwrap();
                            },
                            Err(e) => {
                                server.send(Command::PRIVMSG(target.clone(),
                                    format!("{}! {}", nick, e))).unwrap();
                            }
                        }
                    },
                    _ => (),
                }
            }
        });
        tx
    })
}

fn main() {
    let server = IrcServer::new("config.json").unwrap();
    server.identify().unwrap();
    join_start_channels(&server).unwrap();
    let mut user_senders = HashMap::new();

    for message in server.iter() {
        let message = message.unwrap();
        match message.command {
            Command::PRIVMSG(_, ref msg) => {
                if msg.starts_with(LEADER) {
                    if let Some(chan) = message.source_nickname()
                            .map(|nick| find_or_spawn(&server,
                                                      &mut user_senders,
                                                      nick)) {
                        chan.send(message.clone()).unwrap();
                    }
                }
            },
            _ => (),
        }
    }
}
<|endoftext|>