<commit_before>#[macro_use]
extern crate clap;
#[macro_use]
extern crate lazy_static;

extern crate libc;
extern crate scmp;
extern crate tempdir;

use std::fs;
use std::env;
use std::ffi::OsStr;
use std::ffi::CString;
use std::io::Error;
use std::os::raw::c_void;
use std::os::unix::process::CommandExt;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use scmp::*;

unsafe fn allow_syscall(ctx : *mut c_void, nr : u32) {
    assert!(seccomp_rule_add_array(ctx, SCMP_ACT_ALLOW, nr as i32, 0, std::ptr::null()) == 0);
}

fn setup_seccomp() -> Result<(), Error> {
    unsafe {
        let ctx = seccomp_init(SCMP_ACT_TRAP);
        assert!(!ctx.is_null());
        allow_syscall(ctx, __NR_execve);
        allow_syscall(ctx, __NR_brk);
        allow_syscall(ctx, __NR_access);
        allow_syscall(ctx, __NR_mmap);
        allow_syscall(ctx, __NR_open);
        allow_syscall(ctx, __NR_read);
        allow_syscall(ctx, __NR_write);
        allow_syscall(ctx, __NR_stat);
        allow_syscall(ctx, __NR_fstat);
        allow_syscall(ctx, __NR_close);
        allow_syscall(ctx, __NR_mprotect);
        allow_syscall(ctx, __NR_arch_prctl);
        allow_syscall(ctx, __NR_munmap);
        allow_syscall(ctx, __NR_set_tid_address);
        allow_syscall(ctx, __NR_set_robust_list);
        allow_syscall(ctx, __NR_rt_sigaction);
        allow_syscall(ctx, __NR_rt_sigprocmask);
        allow_syscall(ctx, __NR_getrlimit);
        allow_syscall(ctx, __NR_statfs);
        allow_syscall(ctx, __NR_fcntl);
        allow_syscall(ctx, __NR_geteuid);
        allow_syscall(ctx, __NR_umask);
        allow_syscall(ctx, __NR_pipe);
        allow_syscall(ctx, __NR_clone);
        allow_syscall(ctx, __NR_wait4);
        allow_syscall(ctx, __NR_exit_group);
        allow_syscall(ctx, __NR_dup);
        assert!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::FIOCLEX, datum_b: 0,
        }) == 0);
        assert!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::FIONBIO, datum_b: 0,
        }) == 0);
        assert!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::TCGETS, datum_b: 0,
        }) == 0);
        assert!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::TIOCGWINSZ, datum_b: 0,
        }) == 0);
        allow_syscall(ctx, __NR_getpid);
        allow_syscall(ctx, __NR_gettid);
        allow_syscall(ctx, __NR_tgkill);
        allow_syscall(ctx, __NR_rt_sigreturn);
        allow_syscall(ctx, __NR_socket);
        allow_syscall(ctx, __NR_connect);
        allow_syscall(ctx, __NR_lseek);
        allow_syscall(ctx, __NR_openat);
        allow_syscall(ctx, __NR_unlinkat);
        allow_syscall(ctx, __NR_utimensat);
        allow_syscall(ctx, __NR_lstat);
        allow_syscall(ctx, __NR_fchmod);
        allow_syscall(ctx, __NR_unlink);
        allow_syscall(ctx, __NR_utime);
        allow_syscall(ctx, __NR_futex);
        allow_syscall(ctx, __NR_chmod);
        allow_syscall(ctx, __NR_getuid);
        allow_syscall(ctx, __NR_getgid);
        allow_syscall(ctx, __NR_getppid);
        allow_syscall(ctx, __NR_getcwd);
        allow_syscall(ctx, __NR_getegid);
        allow_syscall(ctx, __NR_getdents);
        allow_syscall(ctx, __NR_readlink);
        allow_syscall(ctx, __NR_mkdirat);
        allow_syscall(ctx, __NR_mkdir);
        allow_syscall(ctx, __NR_madvise);
        allow_syscall(ctx, __NR_exit);
        assert!(seccomp_load(ctx) == 0);
    }
    return Ok(());
}

const RENAME_NOREPLACE : u64 = 1;

fn path_to_cstring(path : &Path) -> CString {
    return CString::new(path.as_os_str().as_bytes()).unwrap();
}

fn rename_noreplace(path0 : &Path, path1 : &Path) -> Result<(), Error> {
    unsafe {
        if libc::syscall(__NR_renameat2 as i64, libc::AT_FDCWD, path_to_cstring(path0).as_ptr(), libc::AT_FDCWD, path_to_cstring(path1).as_ptr(), RENAME_NOREPLACE, 0) == 0 {
            return Ok(());
        } else {
            return Err(Error::last_os_error());
        }
    }
}

fn rename_or_suffix(path0 : &Path, path1 : &Path) -> Result<PathBuf, Error> {
    let rv = rename_noreplace(path0, path1);
    if let Err(err) = rv {
        if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
            return Err(err);
        }
        for suffix in 1.. {
            let mut builder = path1.as_os_str().to_os_string();
            builder.push(format!(".{}", suffix));
            let rv = rename_noreplace(path0, Path::new(&builder));
            if let Err(err) = rv {
                if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
                    return Err(err);
                }
                continue;
            }
            return Ok(Path::new(&builder).to_path_buf());
        }
        return Ok(PathBuf::new()); // XXX Unreachable
    } else {
        return Ok(path1.to_path_buf());
    }
}

struct ArchiveType {
    extensions: Vec<&'static str>,
    extract_cmd: Vec<&'static str>,
}

lazy_static! {
    static ref ARCHIVE_TYPES : Vec<ArchiveType> = vec![
        ArchiveType {
            extensions: vec![
                ".tgz",
                ".tar.gz",
                ".tar.Z",
                ".tbz2",
                ".tar.bz2",
                ".tlz",
                ".tar.lz",
                ".tar.lzma",
                ".tar.lzo",
                ".tar.xz",
            ],
            extract_cmd: vec!["tar", "-xf"],
        },
        ArchiveType {
            extensions: vec![
                ".zip",
            ],
            extract_cmd: vec!["unzip", "--"],
        },
        ArchiveType {
            extensions: vec![
                ".part1.rar",
                ".rar",
            ],
            extract_cmd: vec!["unrar", "x", "--"],
        },
        ArchiveType {
            extensions: vec![
                ".7z",
            ],
            extract_cmd: vec!["7z", "x", "--"],
        },
    ];
}

fn main() {
    let matches = clap_app!(myapp =>
        (@arg ARCHIVE: +required ... "Archives to extract")
    ).get_matches();

    let mut found = false;

    for arch in matches.values_of_os("ARCHIVE").unwrap() {
        let arch = Path::new(arch);
        let arch_bytes = arch.as_os_str().as_bytes();
        println!("Extract {:?}", arch);
        for at in ARCHIVE_TYPES.iter() {
            for &ext in &at.extensions {
                let ext_bytes = ext.as_bytes();
                if !arch_bytes.ends_with(ext_bytes) {
                    continue;
                }
                found = true;

                let noext : &OsStr = OsStrExt::from_bytes(&arch_bytes[0..arch_bytes.len()-ext_bytes.len()]);
                let stripped =
                    if let Some(noext) = Path::new(noext).file_name() {
                        noext
                    } else {
                        OsStr::new("extracted")
                    };
                let cmd = at.extract_cmd[0];
                let tmpdir = tempdir::TempDir::new_in(
                    env::current_dir().expect("Unable to get the current directory"),
                    stripped.to_string_lossy().to_mut().as_str()).expect("Unable to create temporary directory");
                let status = Command::new(cmd)
                    .args(&at.extract_cmd[1..])
                    .arg(fs::canonicalize(&arch).expect("Unable to find archive"))
                    .current_dir(&tmpdir)
                    .before_exec(setup_seccomp)
                    .status()
                    .expect(format!("Failed to launch {}", cmd).as_str());
                assert!(status.success(), format!("{} wasn't successful", cmd));
                let extracted_path = tmpdir.into_path();
                let mut dir_list = fs::read_dir(&extracted_path).expect("Unable to read the extraction directory");
                if let Some(path) = dir_list.next() {
                    let path = path.expect("Unable to iterate the extraction directory");
                    if let Some(path1) = dir_list.next() {
                        path1.expect("Unable to iterate the extraction directory");
                        let newname = rename_or_suffix(&extracted_path, Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                    } else {
                        let newname = rename_or_suffix(&path.path(), Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                        fs::remove_dir(&extracted_path).expect("Failed to remove empty extraction directory");
                    }
                } else {
                    println!("No files were extracted");
                }
                break;
            }
        }
        if !found {
            println!("Can't handle {:?}", arch);
        }
    }
}

<commit_msg>Lint with clippy<commit_after>#![cfg_attr(feature = "cargo-clippy", allow(needless_return))]

#[macro_use]
extern crate clap;
#[macro_use]
extern crate lazy_static;

extern crate libc;
extern crate scmp;
extern crate tempdir;

use std::fs;
use std::env;
use std::ffi::OsStr;
use std::ffi::CString;
use std::io::Error;
use std::os::raw::c_void;
use std::os::unix::process::CommandExt;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use scmp::*;

unsafe fn allow_syscall(ctx : *mut c_void, nr : u32) {
    assert_eq!(seccomp_rule_add_array(ctx, SCMP_ACT_ALLOW, nr as i32, 0, std::ptr::null()), 0);
}

fn setup_seccomp() -> Result<(), Error> {
    unsafe {
        let ctx = seccomp_init(SCMP_ACT_TRAP);
        assert!(!ctx.is_null());
        allow_syscall(ctx, __NR_execve);
        allow_syscall(ctx, __NR_brk);
        allow_syscall(ctx, __NR_access);
        allow_syscall(ctx, __NR_mmap);
        allow_syscall(ctx, __NR_open);
        allow_syscall(ctx, __NR_read);
        allow_syscall(ctx, __NR_write);
        allow_syscall(ctx, __NR_stat);
        allow_syscall(ctx, __NR_fstat);
        allow_syscall(ctx, __NR_close);
        allow_syscall(ctx, __NR_mprotect);
        allow_syscall(ctx, __NR_arch_prctl);
        allow_syscall(ctx, __NR_munmap);
        allow_syscall(ctx, __NR_set_tid_address);
        allow_syscall(ctx, __NR_set_robust_list);
        allow_syscall(ctx, __NR_rt_sigaction);
        allow_syscall(ctx, __NR_rt_sigprocmask);
        allow_syscall(ctx, __NR_getrlimit);
        allow_syscall(ctx, __NR_statfs);
        allow_syscall(ctx, __NR_fcntl);
        allow_syscall(ctx, __NR_geteuid);
        allow_syscall(ctx, __NR_umask);
        allow_syscall(ctx, __NR_pipe);
        allow_syscall(ctx, __NR_clone);
        allow_syscall(ctx, __NR_wait4);
        allow_syscall(ctx, __NR_exit_group);
        allow_syscall(ctx, __NR_dup);
        assert_eq!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::FIOCLEX, datum_b: 0,
        }), 0);
        assert_eq!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::FIONBIO, datum_b: 0,
        }), 0);
        assert_eq!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::TCGETS, datum_b: 0,
        }), 0);
        assert_eq!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::TIOCGWINSZ, datum_b: 0,
        }), 0);
        allow_syscall(ctx, __NR_getpid);
        allow_syscall(ctx, __NR_gettid);
        allow_syscall(ctx, __NR_tgkill);
        allow_syscall(ctx, __NR_rt_sigreturn);
        allow_syscall(ctx, __NR_socket);
        allow_syscall(ctx, __NR_connect);
        allow_syscall(ctx, __NR_lseek);
        allow_syscall(ctx, __NR_openat);
        allow_syscall(ctx, __NR_unlinkat);
        allow_syscall(ctx, __NR_utimensat);
        allow_syscall(ctx, __NR_lstat);
        allow_syscall(ctx, __NR_fchmod);
        allow_syscall(ctx, __NR_unlink);
        allow_syscall(ctx, __NR_utime);
        allow_syscall(ctx, __NR_futex);
        allow_syscall(ctx, __NR_chmod);
        allow_syscall(ctx, __NR_getuid);
        allow_syscall(ctx, __NR_getgid);
        allow_syscall(ctx, __NR_getppid);
        allow_syscall(ctx, __NR_getcwd);
        allow_syscall(ctx, __NR_getegid);
        allow_syscall(ctx, __NR_getdents);
        allow_syscall(ctx, __NR_readlink);
        allow_syscall(ctx, __NR_mkdirat);
        allow_syscall(ctx, __NR_mkdir);
        allow_syscall(ctx, __NR_madvise);
        allow_syscall(ctx, __NR_exit);
        assert_eq!(seccomp_load(ctx), 0);
    }
    return Ok(());
}

const RENAME_NOREPLACE : u64 = 1;

fn path_to_cstring(path : &Path) -> CString {
    return CString::new(path.as_os_str().as_bytes()).unwrap();
}

fn rename_noreplace(path0 : &Path, path1 : &Path) -> Result<(), Error> {
    unsafe {
        if libc::syscall(__NR_renameat2 as i64, libc::AT_FDCWD, path_to_cstring(path0).as_ptr(), libc::AT_FDCWD, path_to_cstring(path1).as_ptr(), RENAME_NOREPLACE, 0) == 0 {
            return Ok(());
        } else {
            return Err(Error::last_os_error());
        }
    }
}

fn rename_or_suffix(path0 : &Path, path1 : &Path) -> Result<PathBuf, Error> {
    let rv = rename_noreplace(path0, path1);
    if let Err(err) = rv {
        if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
            return Err(err);
        }
        for suffix in 1.. {
            let mut builder = path1.as_os_str().to_os_string();
            builder.push(format!(".{}", suffix));
            let rv = rename_noreplace(path0, Path::new(&builder));
            if let Err(err) = rv {
                if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
                    return Err(err);
                }
                continue;
            }
            return Ok(Path::new(&builder).to_path_buf());
        }
        return Ok(PathBuf::new()); // XXX Unreachable
    } else {
        return Ok(path1.to_path_buf());
    }
}

struct ArchiveType {
    extensions: Vec<&'static str>,
    extract_cmd: Vec<&'static str>,
}

lazy_static! {
    static ref ARCHIVE_TYPES : Vec<ArchiveType> = vec![
        ArchiveType {
            extensions: vec![
                ".tgz",
                ".tar.gz",
                ".tar.Z",
                ".tbz2",
                ".tar.bz2",
                ".tlz",
                ".tar.lz",
                ".tar.lzma",
                ".tar.lzo",
                ".tar.xz",
            ],
            extract_cmd: vec!["tar", "-xf"],
        },
        ArchiveType {
            extensions: vec![
                ".zip",
            ],
            extract_cmd: vec!["unzip", "--"],
        },
        ArchiveType {
            extensions: vec![
                ".part1.rar",
                ".rar",
            ],
            extract_cmd: vec!["unrar", "x", "--"],
        },
        ArchiveType {
            extensions: vec![
                ".7z",
            ],
            extract_cmd: vec!["7z", "x", "--"],
        },
    ];
}

fn main() {
    let matches = clap_app!(myapp =>
        (@arg ARCHIVE: +required ... "Archives to extract")
    ).get_matches();

    let mut found = false;

    for arch in matches.values_of_os("ARCHIVE").unwrap() {
        let arch = Path::new(arch);
        let arch_bytes = arch.as_os_str().as_bytes();
        println!("Extract {:?}", arch);
        for at in ARCHIVE_TYPES.iter() {
            for &ext in &at.extensions {
                let ext_bytes = ext.as_bytes();
                if !arch_bytes.ends_with(ext_bytes) {
                    continue;
                }
                found = true;

                let noext : &OsStr = OsStrExt::from_bytes(&arch_bytes[0..arch_bytes.len()-ext_bytes.len()]);
                let stripped =
                    if let Some(noext) = Path::new(noext).file_name() {
                        noext
                    } else {
                        OsStr::new("extracted")
                    };
                let cmd = at.extract_cmd[0];
                let tmpdir = tempdir::TempDir::new_in(
                    env::current_dir().expect("Unable to get the current directory"),
                    stripped.to_string_lossy().to_mut().as_str()).expect("Unable to create temporary directory");
                let status = Command::new(cmd)
                    .args(&at.extract_cmd[1..])
                    .arg(fs::canonicalize(&arch).expect("Unable to find archive"))
                    .current_dir(&tmpdir)
                    .before_exec(setup_seccomp)
                    .status()
                    .expect(format!("Failed to launch {}", cmd).as_str());
                assert!(status.success(), format!("{} wasn't successful", cmd));
                let extracted_path = tmpdir.into_path();
                let mut dir_list = fs::read_dir(&extracted_path).expect("Unable to read the extraction directory");
                if let Some(path) = dir_list.next() {
                    let path = path.expect("Unable to iterate the extraction directory");
                    if let Some(path1) = dir_list.next() {
                        path1.expect("Unable to iterate the extraction directory");
                        let newname = rename_or_suffix(&extracted_path, Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                    } else {
                        let newname = rename_or_suffix(&path.path(), Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                        fs::remove_dir(&extracted_path).expect("Failed to remove empty extraction directory");
                    }
                } else {
                    println!("No files were extracted");
                }
                break;
            }
        }
        if !found {
            println!("Can't handle {:?}", arch);
        }
    }
}

<|endoftext|>


<commit_before>fn main() {

}
<commit_msg>Remove unused main.rs<commit_after><|endoftext|>


<commit_before>extern crate discord;

mod modules;

use discord::Discord;
use discord::model::Event;
use std::env;
use modules::KModule;

fn main() {
    let mods: Vec<Box<KModule>> = vec![
        Box::new(modules::About)
    ];

    for m in &mods {
        m.init();
    }

    let bot = Discord::from_bot_token(
        &env::var("DISCORD_TOKEN").expect("Expecting token in $DISCORD_TOKEN")
    ).expect("Login failed. Wrong token?");

    let (mut connection, _) = bot.connect().expect("Error while connecting to discord!");

    println!("Bot ready. Starting event loop!");

    loop {
        match connection.recv_event() {
            Ok(Event::MessageCreate(message)) => {}

            Ok(_) => {}

            Err(discord::Error::Closed(code, body)) => {
                println!("Gateway closed with code {:?} : {:?}", code, body);
                break;
            }

            Err(err) => println!("Received error: {:?}", err),
        }
    }
}
<commit_msg>Add hipsterized ASCII logo<commit_after>extern crate discord;

use discord::Discord;
use discord::model::Event;
use std::env;

mod modules;
use modules::*;

fn main() {
    print_logo();

    let mods: Vec<Box<KModule>> = vec![
        Box::new(modules::About)
    ];

    for m in &mods {
        println!("Loading module {:?}...", m.name());
        m.init();
        println!("Done");
    }

    let bot = Discord::from_bot_token(
        &env::var("DISCORD_TOKEN").expect("Expecting token in $DISCORD_TOKEN")
    ).expect("Login failed. Wrong token?");

    let (mut connection, _) = bot.connect().expect("Error while connecting to discord!");

    println!("Bot ready. Starting event loop!");

    loop {
        match connection.recv_event() {
            Ok(Event::MessageCreate(message)) => {}

            Ok(_) => {}

            Err(discord::Error::Closed(code, body)) => {
                println!("Gateway closed with code {:?} : {:?}", code, body);
                break;
            }

            Err(err) => println!("Received error: {:?}", err),
        }
    }
}

fn print_logo() {
    let v = vec![
        "",
        "Welcome to...",
        " ▄    ▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄        ▄ ",
        "▐░▌  ▐░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░▌      ▐░▌",
        "▐░▌ ▐░▌ ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀▀▀ ▐░▌░▌     ▐░▌",
        "▐░▌▐░▌  ▐░▌       ▐░▌▐░▌       ▐░▌▐░▌          ▐░▌▐░▌    ▐░▌",
        "▐░▌░▌   ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░▌ ▐░▌   ▐░▌",
        "▐░░▌    ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░▌  ▐░▌  ▐░▌",
        "▐░▌░▌   ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀█░█▀▀ ▐░█▀▀▀▀▀▀▀▀▀ ▐░▌   ▐░▌ ▐░▌",
        "▐░▌▐░▌  ▐░▌       ▐░▌▐░▌     ▐░▌  ▐░▌          ▐░▌    ▐░▌▐░▌",
        "▐░▌ ▐░▌ ▐░▌       ▐░▌▐░▌      ▐░▌ ▐░█▄▄▄▄▄▄▄▄▄ ▐░▌     ▐░▐░▌",
        "▐░▌  ▐░▌▐░▌       ▐░▌▐░▌       ▐░▌▐░░░░░░░░░░░▌▐░▌      ▐░░▌",
        " ▀    ▀  ▀         ▀  ▀         ▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀        ▀▀ ",
        "Version 0.1.0!                                        INDEV!",
        ""
    ];

    for line in v {
        println!("{}", line);
    }
}<|endoftext|>


<commit_before>extern crate base64;
extern crate hyper;
extern crate hyper_native_tls;
extern crate pem;
#[macro_use]
extern crate prettytable;
extern crate ring;
extern crate serde_json;
extern crate url;

extern crate ct_submitter;

use std::{env, process};
use std::fs::File;
use std::io::Read;
use std::time::Duration;

use ring::digest;

use ct_submitter::{fetch_trusted_ct_logs, submit_cert_to_logs, AddChainRequest};

fn pems_to_chain(data: &str) -> Vec<Vec<u8>> {
    return pem::parse_many(data)
               .into_iter()
               .filter(|p| p.tag == "CERTIFICATE")
               .map(|p| p.contents)
               .collect::<Vec<_>>();
}

fn build_chain(http_client: &hyper::Client, cert: &[u8]) -> Vec<Vec<u8>> {
    let body = url::form_urlencoded::Serializer::new(String::new())
        .append_pair("b64cert", &base64::encode(cert))
        .finish();
    let body_bytes = body.as_bytes();
    let response = http_client
        .post("https://crt.sh/gen-add-chain")
        .header(hyper::header::ContentType::form_url_encoded())
        .body(hyper::client::Body::BufBody(body_bytes, body_bytes.len()))
        .send()
        .unwrap();

    let add_chain_request: AddChainRequest = serde_json::from_reader(response).unwrap();
    return add_chain_request
        .chain
        .iter()
        .map(|c| base64::decode(c).unwrap())
        .collect();
}

fn main() {
    if env::args().len() == 1 {
        println!("Usage: {} <cert-or-chain.pem ...>", env::args().next().unwrap());
        process::exit(1);
    }

    let mut http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_native_tls::NativeTlsClient::new().unwrap())
    );
    let logs = fetch_trusted_ct_logs(&http_client);

    for path in env::args().skip(1) {
        println!("Submitting {} ...", path);

        let mut contents = String::new();
        File::open(path)
            .unwrap()
            .read_to_string(&mut contents)
            .unwrap();

        let mut chain = pems_to_chain(&contents);
        if chain.len() == 1 {
            // TODO: There's got to be some way to do this ourselves, instead of using crt.sh as a
            // glorified AIA chaser.
            println!("Only one certificate in chain, using crt.sh to build a full chain ...");
            chain = build_chain(&http_client, &chain[0]);
        }
        let scts = submit_cert_to_logs(&http_client, &logs, &chain);

        let mut table = prettytable::Table::new();
        table.add_row(row!["Log", "SCT"]);
        for (log, sct) in scts {
            table.add_row(row![log.description, base64::encode(&sct.to_raw_bytes())]);
        }
        table.printstd();

        // TODO: is there a better way to do this hex-encoding?
        println!("Find the cert on crt.sh: https://crt.sh?q={}",
                 digest::digest(&digest::SHA256, &chain[0])
                     .as_ref()
                     .iter()
                     .map(|b| format!("{:02X}", b))
                     .collect::<String>());
         println!();
         println!();
    }

}
<commit_msg>Comment<commit_after>extern crate base64;
extern crate hyper;
extern crate hyper_native_tls;
extern crate pem;
#[macro_use]
extern crate prettytable;
extern crate ring;
extern crate serde_json;
extern crate url;

extern crate ct_submitter;

use std::{env, process};
use std::fs::File;
use std::io::Read;

use ring::digest;

use ct_submitter::{fetch_trusted_ct_logs, submit_cert_to_logs, AddChainRequest};

fn pems_to_chain(data: &str) -> Vec<Vec<u8>> {
    return pem::parse_many(data)
               .into_iter()
               .filter(|p| p.tag == "CERTIFICATE")
               .map(|p| p.contents)
               .collect::<Vec<_>>();
}

fn build_chain(http_client: &hyper::Client, cert: &[u8]) -> Vec<Vec<u8>> {
    let body = url::form_urlencoded::Serializer::new(String::new())
        .append_pair("b64cert", &base64::encode(cert))
        .finish();
    let body_bytes = body.as_bytes();
    let response = http_client
        .post("https://crt.sh/gen-add-chain")
        .header(hyper::header::ContentType::form_url_encoded())
        .body(hyper::client::Body::BufBody(body_bytes, body_bytes.len()))
        .send()
        .unwrap();

    let add_chain_request: AddChainRequest = serde_json::from_reader(response).unwrap();
    return add_chain_request
        .chain
        .iter()
        .map(|c| base64::decode(c).unwrap())
        .collect();
}

fn main() {
    if env::args().len() == 1 {
        println!("Usage: {} <cert-or-chain.pem ...>", env::args().next().unwrap());
        process::exit(1);
    }

    let http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_native_tls::NativeTlsClient::new().unwrap())
    );
    // TODO: timeout on the http_client, but for submit_cert_to_logs only, not build_chain
    let logs = fetch_trusted_ct_logs(&http_client);

    for path in env::args().skip(1) {
        println!("Submitting {} ...", path);

        let mut contents = String::new();
        File::open(path)
            .unwrap()
            .read_to_string(&mut contents)
            .unwrap();

        let mut chain = pems_to_chain(&contents);
        if chain.len() == 1 {
            // TODO: There's got to be some way to do this ourselves, instead of using crt.sh as a
            // glorified AIA chaser.
            println!("Only one certificate in chain, using crt.sh to build a full chain ...");
            chain = build_chain(&http_client, &chain[0]);
        }
        let scts = submit_cert_to_logs(&http_client, &logs, &chain);

        let mut table = prettytable::Table::new();
        table.add_row(row!["Log", "SCT"]);
        for (log, sct) in scts {
            table.add_row(row![log.description, base64::encode(&sct.to_raw_bytes())]);
        }
        table.printstd();

        // TODO: is there a better way to do this hex-encoding?
        println!("Find the cert on crt.sh: https://crt.sh?q={}",
                 digest::digest(&digest::SHA256, &chain[0])
                     .as_ref()
                     .iter()
                     .map(|b| format!("{:02X}", b))
                     .collect::<String>());
         println!();
         println!();
    }

}
<|endoftext|>


<commit_before>#![cfg(not(test))]
#![allow(unused_variables)]
#![allow(dead_code)]

extern crate rules;

use rules::parse;
use rules::collapse;

fn test_collapse(regex: &str) {
    let parsed = match parse::parse(regex) {
        Ok(vec) => vec,
        Err(e) => {
            println!("{}", e);
            return;
        }
    };
    println!("Parsed:\n{:?}", &parsed);

    let collapsed = collapse::collapse(parsed);
    println!("Collapsed:\n{:?}", &collapsed);
}

fn main() {
    test_collapse(r" ab<[..]> ");
}
<commit_msg>Update main for when comments are ignored<commit_after>#![cfg(not(test))]
#![allow(unused_variables)]
#![allow(dead_code)]

extern crate rules;

use rules::re::Regex;

fn main() {
    let re = Regex::new(r"pine  // This is a comment
                          apple // This is another comment");
    println!("match is {}", re.is_match("pineapple"));
}
<|endoftext|>


<commit_before>extern crate mmap;
extern crate time;
extern crate timely;
extern crate getopts;

use timely::progress::timestamp::RootTimestamp;
use timely::dataflow::operators::*;
use timely::dataflow::channels::pact::Exchange;

mod typedrw;
mod graphmap;
mod sorting;
use graphmap::GraphMMap;
use sorting::{SegmentList, radix_sort_32};
use std::fs::File;
use std::io::{BufWriter, Write};

fn main () {

    let filename = std::env::args().skip(1).next().unwrap();
    let strategy = std::env::args().skip(2).next().unwrap() == "process";

    // currently need timely's full option set to parse args
    let mut opts = getopts::Options::new();
    opts.optopt("w", "workers", "", "");
    opts.optopt("p", "process", "", "");
    opts.optopt("n", "processes", "", "");
    opts.optopt("h", "hostfile", "", "");

    opts.optopt("o", "output", "", "");

    if let Ok(matches) = opts.parse(std::env::args().skip(3)) {

        let workers: usize = matches.opt_str("w").map(|x| x.parse().unwrap_or(1)).unwrap_or(1);

        let timely_opt_keys = ["w", "p", "n", "h"];
        let matches_copy = matches.clone();
        let timely_args: Vec<String> = timely_opt_keys.into_iter()
            .filter_map(|k| matches_copy.opt_str(k).map(|x| vec![format!("-{}", k), x]))
            .flat_map(|x| x)
            .collect();

        timely::execute_from_args(timely_args.into_iter(), move |root| {

            let index = root.index() as usize;
            let peers = root.peers() as usize;

            let start = time::precise_time_s();

            let nodes = GraphMMap::new(&filename).nodes();

            let mut segments = SegmentList::new(1024); // list of edge segments

            let mut src = vec![];   // holds ranks
            let mut deg = vec![];   // holds source degrees
            let mut rev = vec![];   // holds (dst, deg) pairs
            let mut trn = vec![];   // holds transposed sources

            let mut going = start;

            let peer_output_path = matches.opt_str("o").map(
                |p| replace_placeholder_or_append_path_suffix(&p, &index.to_string())
            );

            let mut input = root.dataflow(|builder| {

                let (input, edges) = builder.new_input::<(u32, u32)>();
                let (cycle, ranks) = builder.loop_variable::<(u32, f32)>(20, 1);

                let mut ranks = edges.binary_notify(&ranks,
                                    Exchange::new(|x: &(u32,u32)| x.0 as u64),
                                    Exchange::new(|x: &(u32,f32)| x.0 as u64),
                                    "pagerank",
                                    vec![RootTimestamp::new(0)],
                                    move |input1, input2, output, notificator| {

                    // receive incoming edges (should only be iter 0)
                    input1.for_each(|_iter, data| {
                        segments.push(data.drain(..));
                    });

                    // all inputs received for iter, commence multiplication
                    notificator.for_each(|iter,_,_| {

                        let now = time::now();

                        if index == 0 { println!("{}:{}:{}.{} starting iteration {}", now.tm_hour, now.tm_min, now.tm_sec, now.tm_nsec, iter.inner); }

                        // if the very first iteration, prepare some stuff.
                        // specifically, transpose edges and sort by destination.
                        if iter.inner == 0 {
                            let (a, b, c) = transpose(segments.finalize(), peers, nodes);
                            deg = a; rev = b; trn = c;
                            src = vec![0.0f32; deg.len()];
                        }

                        // record some timings in order to estimate per-iteration times
                        if iter.inner == 0  { println!("src: {}, dst: {}, edges: {}", src.len(), rev.len(), trn.len()); }
                        if iter.inner == 10 && index == 0 { going = time::precise_time_s(); }
                        if iter.inner == 20 && index == 0 { println!("average: {}", (time::precise_time_s() - going) / 10.0 ); }
                        if iter.inner == 20 && peer_output_path.is_some() {
                            match peer_output_path {
                                Some(ref path) => write_pagerank_values_to(&path, &src, index, peers, nodes),
                                None => {}
                            }
                        }

                        // prepare src for transmitting to destinations
                        for s in 0..src.len() { src[s] = (0.15 + 0.85 * src[s]) / deg[s] as f32; }

                        // wander through destinations
                        let mut trn_slice = &trn[..];
                        let mut session = output.session(&iter);
                        for &(dst, deg) in &rev {
                            let mut accum = 0.0;
                            for &s in &trn_slice[..deg as usize] {
                                // accum += src[s as usize];
                                unsafe { accum += *src.get_unchecked(s as usize); }
                            }
                            trn_slice = &trn_slice[deg as usize..];
                            session.give((dst, accum));
                        }

                        for s in &mut src { *s = 0.0; }
                    });

                    // receive data from workers, accumulate in src
                    input2.for_each(|iter, data| {
                        notificator.notify_at(iter);
                        for &(node, rank) in data.iter() {
                            src[node as usize / peers] += rank;
                        }
                    });
                });

                // optionally, do process-local accumulation
                if strategy {
                    let local_base = workers * (index / workers);
                    let local_index = index % workers;
                    let mut acc = vec![0.0; (nodes / workers) + 1];   // holds ranks
                    ranks = ranks.unary_notify(
                        Exchange::new(move |x: &(u32,f32)| (local_base as u64 + (x.0 as u64 % workers as u64))),
                        "aggregation",
                        vec![],
                        move |input, output, iterator| {
                            input.for_each(|iter, data| {
                                iterator.notify_at(iter);
                                for &(node, rank) in data.iter() {
                                    acc[node as usize / workers] += rank;
                                }
                            });

                            iterator.for_each(|item,_,_| {
                                output.session(&item)
                                      .give_iterator(acc.drain(..)
                                                        .enumerate()
                                                        .filter(|x| x.1 != 0.0)
                                                        .map(|(u,f)| ((u * workers + local_index) as u32, f)));

                                for _ in 0..(1 + (nodes/workers)) { acc.push(0.0); }
                            });
                        }
                    );
                }

                ranks.connect_loop(cycle);

                input
            });

            // introduce edges into the computation;
            // allow mmaped file to drop
            {
                let graph = GraphMMap::new(&filename);
                for node in 0..graph.nodes() {
                    if node % peers == index {
                        for dst in graph.edges(node) {
                            input.send(((node + 1) as u32, *dst as u32));
                        }
                    }
                }
            }
            input.close();
            while root.step() { }

            if index == 0 { println!("elapsed: {}", time::precise_time_s() - start); }
        }).unwrap();
    }
    else {
        println!("error parsing arguments");
        println!("usage:\tpagerank <source> (worker|process) [timely options]");
    }
}

// returns [src/peers] degrees, (dst, deg) pairs, and a list of [src/peers] endpoints
fn transpose(mut edges: Vec<Vec<(u32, u32)>>, peers: usize, nodes: usize) -> (Vec<u32>, Vec<(u32, u32)>, Vec<u32>)  {

    let mut deg = vec![0; (nodes as usize / peers) + 1];
    for list in &edges {
        for &(s, _) in list {
            deg[s as usize / peers] += 1;
        }
    }

    radix_sort_32(&mut edges, &mut Vec::new(), &|&(_,d)| d);

    let mut rev = Vec::<(u32,u32)>::with_capacity(deg.len());
    let mut trn = Vec::with_capacity(edges.len() * 1024);
    for list in edges {
        for (s,d) in list {
            let len = rev.len();
            if (len == 0) || (rev[len-1].0 < d) {
                rev.push((d, 0u32));
            }

            let len = rev.len();
            rev[len-1].1 += 1;
            trn.push(s / peers as u32);
        }
    }

    return (deg, rev, trn);
}

fn replace_placeholder_or_append_path_suffix(some_path: &str, value: &str) -> String {
    let result = str::replace(some_path, '?', value);
    if result != some_path {
        // its a different path (contained the placeholder), okay
        return result;
    }
    let p = std::path::Path::new(some_path);
    return format!("{:?}_{}{:?}", p.file_stem().unwrap(), value, p.extension().unwrap());
}

fn write_pagerank_values_to(output_path: &str, values: &Vec<f32>, peer: usize, peers: usize, nodes: usize) {
    println!("writing {} records to {}", values.len(), output_path);
    let mut pagerank_writer = BufWriter::new(File::create(output_path).unwrap());
    pagerank_writer.write("id\tpagerank\n".as_bytes()).unwrap();
    for i in 0..values.len() {
        let node_id = peer + i * peers;
        if node_id < nodes {
            pagerank_writer.write(format!("{}\t{}\n", node_id, values[i]).as_bytes()).unwrap();
        }
    }
}
<commit_msg>fixed quotes in resulting filename<commit_after>extern crate mmap;
extern crate time;
extern crate timely;
extern crate getopts;

use timely::progress::timestamp::RootTimestamp;
use timely::dataflow::operators::*;
use timely::dataflow::channels::pact::Exchange;

mod typedrw;
mod graphmap;
mod sorting;
use graphmap::GraphMMap;
use sorting::{SegmentList, radix_sort_32};
use std::fs::File;
use std::io::{BufWriter, Write};

fn main () {

    let filename = std::env::args().skip(1).next().unwrap();
    let strategy = std::env::args().skip(2).next().unwrap() == "process";

    // currently need timely's full option set to parse args
    let mut opts = getopts::Options::new();
    opts.optopt("w", "workers", "", "");
    opts.optopt("p", "process", "", "");
    opts.optopt("n", "processes", "", "");
    opts.optopt("h", "hostfile", "", "");

    opts.optopt("o", "output", "", "");

    if let Ok(matches) = opts.parse(std::env::args().skip(3)) {

        let workers: usize = matches.opt_str("w").map(|x| x.parse().unwrap_or(1)).unwrap_or(1);

        let timely_opt_keys = ["w", "p", "n", "h"];
        let matches_copy = matches.clone();
        let timely_args: Vec<String> = timely_opt_keys.into_iter()
            .filter_map(|k| matches_copy.opt_str(k).map(|x| vec![format!("-{}", k), x]))
            .flat_map(|x| x)
            .collect();

        timely::execute_from_args(timely_args.into_iter(), move |root| {

            let index = root.index() as usize;
            let peers = root.peers() as usize;

            let start = time::precise_time_s();

            let nodes = GraphMMap::new(&filename).nodes();

            let mut segments = SegmentList::new(1024); // list of edge segments

            let mut src = vec![];   // holds ranks
            let mut deg = vec![];   // holds source degrees
            let mut rev = vec![];   // holds (dst, deg) pairs
            let mut trn = vec![];   // holds transposed sources

            let mut going = start;

            let peer_output_path = matches.opt_str("o").map(
                |p| replace_placeholder_or_append_path_suffix(&p, &index.to_string())
            );

            let mut input = root.dataflow(|builder| {

                let (input, edges) = builder.new_input::<(u32, u32)>();
                let (cycle, ranks) = builder.loop_variable::<(u32, f32)>(20, 1);

                let mut ranks = edges.binary_notify(&ranks,
                                    Exchange::new(|x: &(u32,u32)| x.0 as u64),
                                    Exchange::new(|x: &(u32,f32)| x.0 as u64),
                                    "pagerank",
                                    vec![RootTimestamp::new(0)],
                                    move |input1, input2, output, notificator| {

                    // receive incoming edges (should only be iter 0)
                    input1.for_each(|_iter, data| {
                        segments.push(data.drain(..));
                    });

                    // all inputs received for iter, commence multiplication
                    notificator.for_each(|iter,_,_| {

                        let now = time::now();

                        if index == 0 { println!("{}:{}:{}.{} starting iteration {}", now.tm_hour, now.tm_min, now.tm_sec, now.tm_nsec, iter.inner); }

                        // if the very first iteration, prepare some stuff.
                        // specifically, transpose edges and sort by destination.
                        if iter.inner == 0 {
                            let (a, b, c) = transpose(segments.finalize(), peers, nodes);
                            deg = a; rev = b; trn = c;
                            src = vec![0.0f32; deg.len()];
                        }

                        // record some timings in order to estimate per-iteration times
                        if iter.inner == 0  { println!("src: {}, dst: {}, edges: {}", src.len(), rev.len(), trn.len()); }
                        if iter.inner == 10 && index == 0 { going = time::precise_time_s(); }
                        if iter.inner == 20 && index == 0 { println!("average: {}", (time::precise_time_s() - going) / 10.0 ); }
                        if iter.inner == 20 && peer_output_path.is_some() {
                            match peer_output_path {
                                Some(ref path) => write_pagerank_values_to(&path, &src, index, peers, nodes),
                                None => {}
                            }
                        }

                        // prepare src for transmitting to destinations
                        for s in 0..src.len() { src[s] = (0.15 + 0.85 * src[s]) / deg[s] as f32; }

                        // wander through destinations
                        let mut trn_slice = &trn[..];
                        let mut session = output.session(&iter);
                        for &(dst, deg) in &rev {
                            let mut accum = 0.0;
                            for &s in &trn_slice[..deg as usize] {
                                // accum += src[s as usize];
                                unsafe { accum += *src.get_unchecked(s as usize); }
                            }
                            trn_slice = &trn_slice[deg as usize..];
                            session.give((dst, accum));
                        }

                        for s in &mut src { *s = 0.0; }
                    });

                    // receive data from workers, accumulate in src
                    input2.for_each(|iter, data| {
                        notificator.notify_at(iter);
                        for &(node, rank) in data.iter() {
                            src[node as usize / peers] += rank;
                        }
                    });
                });

                // optionally, do process-local accumulation
                if strategy {
                    let local_base = workers * (index / workers);
                    let local_index = index % workers;
                    let mut acc = vec![0.0; (nodes / workers) + 1];   // holds ranks
                    ranks = ranks.unary_notify(
                        Exchange::new(move |x: &(u32,f32)| (local_base as u64 + (x.0 as u64 % workers as u64))),
                        "aggregation",
                        vec![],
                        move |input, output, iterator| {
                            input.for_each(|iter, data| {
                                iterator.notify_at(iter);
                                for &(node, rank) in data.iter() {
                                    acc[node as usize / workers] += rank;
                                }
                            });

                            iterator.for_each(|item,_,_| {
                                output.session(&item)
                                      .give_iterator(acc.drain(..)
                                                        .enumerate()
                                                        .filter(|x| x.1 != 0.0)
                                                        .map(|(u,f)| ((u * workers + local_index) as u32, f)));

                                for _ in 0..(1 + (nodes/workers)) { acc.push(0.0); }
                            });
                        }
                    );
                }

                ranks.connect_loop(cycle);

                input
            });

            // introduce edges into the computation;
            // allow mmaped file to drop
            {
                let graph = GraphMMap::new(&filename);
                for node in 0..graph.nodes() {
                    if node % peers == index {
                        for dst in graph.edges(node) {
                            input.send(((node + 1) as u32, *dst as u32));
                        }
                    }
                }
            }
            input.close();
            while root.step() { }

            if index == 0 { println!("elapsed: {}", time::precise_time_s() - start); }
        }).unwrap();
    }
    else {
        println!("error parsing arguments");
        println!("usage:\tpagerank <source> (worker|process) [timely options]");
    }
}

// returns [src/peers] degrees, (dst, deg) pairs, and a list of [src/peers] endpoints
fn transpose(mut edges: Vec<Vec<(u32, u32)>>, peers: usize, nodes: usize) -> (Vec<u32>, Vec<(u32, u32)>, Vec<u32>)  {

    let mut deg = vec![0; (nodes as usize / peers) + 1];
    for list in &edges {
        for &(s, _) in list {
            deg[s as usize / peers] += 1;
        }
    }

    radix_sort_32(&mut edges, &mut Vec::new(), &|&(_,d)| d);

    let mut rev = Vec::<(u32,u32)>::with_capacity(deg.len());
    let mut trn = Vec::with_capacity(edges.len() * 1024);
    for list in edges {
        for (s,d) in list {
            let len = rev.len();
            if (len == 0) || (rev[len-1].0 < d) {
                rev.push((d, 0u32));
            }

            let len = rev.len();
            rev[len-1].1 += 1;
            trn.push(s / peers as u32);
        }
    }

    return (deg, rev, trn);
}

fn replace_placeholder_or_append_path_suffix(some_path: &str, value: &str) -> String {
    let result = str::replace(some_path, '?', value);
    if result != some_path {
        // its a different path (contained the placeholder), okay
        return result;
    }
    let p = std::path::Path::new(some_path);
    return format!(
        "{}_{}{}",
        p.file_stem().unwrap().to_str().unwrap(),
        value,
        p.extension().map(|x| format!(".{}", x.to_str().unwrap())).unwrap_or("".to_string())
    );
}

fn write_pagerank_values_to(output_path: &str, values: &Vec<f32>, peer: usize, peers: usize, nodes: usize) {
    println!("writing {} records to {}", values.len(), output_path);
    let mut pagerank_writer = BufWriter::new(File::create(output_path).unwrap());
    pagerank_writer.write("id\tpagerank\n".as_bytes()).unwrap();
    for i in 0..values.len() {
        let node_id = peer + i * peers;
        if node_id < nodes {
            pagerank_writer.write(format!("{}\t{}\n", node_id, values[i]).as_bytes()).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>use std;
use time;
use env_logger;
use portaudio;
use rgsl;

fn string_err<Ok, Err: std::fmt::Display>(r: Result<Ok, Err>) -> Result<Ok, String> {
  r.map_err(|err| format!("{}", err))
}

fn sine_wav(f: f32, start: u32, end: u32) -> Vec<f32> {
  let mut buf = Vec::new();

  for t in start .. end {
    let t = t as f32 / f;
    let sample = (t * 440.0 * 2.0 * std::f32::consts::PI).sin();
    let amplitude = 1.0;
    buf.push(sample * amplitude);
  }

  buf
}

fn errorful_main() -> Result<(), String> {
  try!(string_err(env_logger::init()));

  try!(string_err(portaudio::pa::initialize()));

  let f = 44100;
  let buf_size = 1 << 10;
  assert!(buf_size & (buf_size - 1) == 0);

  info!("Reading..");

  let mut stream: portaudio::pa::Stream<f32, f32> = portaudio::pa::Stream::new();
  try!(string_err(
    stream.open_default_blocking(
      f as f64,
      buf_size,
      1,
      0,
      portaudio::pa::SampleFormat::Float32,
    )));
  try!(string_err(stream.start()));

  let mut buf = Vec::new();
  let start_time = time::precise_time_ns();
  while time::precise_time_ns() <= start_time + 2_000_000_000 || (buf.len() & (buf.len() - 1)) != 0 {
    let new = try!(string_err(stream.read(buf_size)));
    assert!(new.len () == buf_size as usize);
    buf.extend(new.into_iter().map(|f| f as f64));
  }

  try!(string_err(stream.stop()));

  info!("Collected {} samples", buf.len());

  info!("Pitch detecting..");

  let len = buf.len();
  let r = rgsl::fft::real_radix2::transform(&mut buf, 1, len);
  if r != rgsl::Value::Success {
    return Err(format!("rgsl returned {:?}", r));
  }

  let (max_idx, _max_val) =
    buf.iter()
      .enumerate()
      .take(len / 2)
      .fold((0, 0.0), |(max_idx, max_val), (i, val)| {
        if *val > max_val {
          (i, *val)
        } else {
          (max_idx, max_val)
        }
      });

  info!("Max index is {}", max_idx);
  info!("Estimated frequency is {}", max_idx as f32 / buf.len() as f32 * f as f32);

  Ok(())
}

#[main]
fn main() {
  errorful_main().unwrap();
}
<commit_msg>info -> println<commit_after>use std;
use time;
use env_logger;
use portaudio;
use rgsl;

fn string_err<Ok, Err: std::fmt::Display>(r: Result<Ok, Err>) -> Result<Ok, String> {
  r.map_err(|err| format!("{}", err))
}

fn sine_wav(f: f32, start: u32, end: u32) -> Vec<f32> {
  let mut buf = Vec::new();

  for t in start .. end {
    let t = t as f32 / f;
    let sample = (t * 440.0 * 2.0 * std::f32::consts::PI).sin();
    let amplitude = 1.0;
    buf.push(sample * amplitude);
  }

  buf
}

fn errorful_main() -> Result<(), String> {
  try!(string_err(env_logger::init()));

  try!(string_err(portaudio::pa::initialize()));

  let f = 44100;
  let buf_size = 1 << 10;
  assert!(buf_size & (buf_size - 1) == 0);

  info!("Reading..");

  let mut stream: portaudio::pa::Stream<f32, f32> = portaudio::pa::Stream::new();
  try!(string_err(
    stream.open_default_blocking(
      f as f64,
      buf_size,
      1,
      0,
      portaudio::pa::SampleFormat::Float32,
    )));
  try!(string_err(stream.start()));

  let mut buf = Vec::new();
  let start_time = time::precise_time_ns();
  while time::precise_time_ns() <= start_time + 2_000_000_000 || (buf.len() & (buf.len() - 1)) != 0 {
    let new = try!(string_err(stream.read(buf_size)));
    assert!(new.len () == buf_size as usize);
    buf.extend(new.into_iter().map(|f| f as f64));
  }

  try!(string_err(stream.stop()));

  info!("Collected {} samples", buf.len());

  info!("Pitch detecting..");

  let len = buf.len();
  let r = rgsl::fft::real_radix2::transform(&mut buf, 1, len);
  if r != rgsl::Value::Success {
    return Err(format!("rgsl returned {:?}", r));
  }

  let (max_idx, _max_val) =
    buf.iter()
      .enumerate()
      .take(len / 2)
      .fold((0, 0.0), |(max_idx, max_val), (i, val)| {
        if *val > max_val {
          (i, *val)
        } else {
          (max_idx, max_val)
        }
      });

  info!("Max index is {}", max_idx);
  println!("Estimated frequency is {}", max_idx as f32 / buf.len() as f32 * f as f32);

  Ok(())
}

#[main]
fn main() {
  errorful_main().unwrap();
}
<|endoftext|>


<commit_before>// run-pass
// ignore-tidy-cr

// this file has some special \r\n endings (use xxd to see them)

fn main() {assert_eq!(b"", b"\
                                   ");
assert_eq!(b"\n", b"
");
}
<commit_msg>Fix regression in line ending test<commit_after>// run-pass
// ignore-tidy-cr

// this file has some special \r\n endings (use xxd to see them)

fn main() {assert_eq!(b"", b"\
                                   ");
assert_eq!(b"\n", b"
");
}
<|endoftext|>


<commit_before>extern crate rust_guessing_game;

use std::old_io as io;
use std::rand;
use std::cmp::Ordering;

use rust_guessing_game::my_funcs;

#[cfg(not(test))]
fn main() {
    println!("Guess the magic number!");
    let magic_number = ( rand::random::<usize>() % 100u ) + 1u;
    loop {
        let input = io::stdin().read_line().ok().expect("That was bad input");
        let input_optoin_usize: Option<usize> = input.parse();
        let input_usize = match input_optoin_usize {
            Some(num) => num,
            None      => {
                println!("Please input a number");
                continue;
            }
        };
        match my_funcs::compare(input_usize, magic_number) {
            Ordering::Less    => println!("Guess higher."),
            Ordering::Greater => println!("Guess lower."),
            Ordering::Equal   => {
                println!("You win!");
                return
            },
        }
    }
}
<commit_msg>Remove 'u' from number literals<commit_after>extern crate rust_guessing_game;

use std::old_io as io;
use std::rand;
use std::cmp::Ordering;

use rust_guessing_game::my_funcs;

#[cfg(not(test))]
fn main() {
    println!("Guess the magic number!");
    let magic_number = ( rand::random::<usize>() % 100 ) + 1;
    loop {
        let input = io::stdin().read_line().ok().expect("That was bad input");
        let input_optoin_usize: Option<usize> = input.parse();
        let input_usize = match input_optoin_usize {
            Some(num) => num,
            None      => {
                println!("Please input a number");
                continue;
            }
        };
        match my_funcs::compare(input_usize, magic_number) {
            Ordering::Less    => println!("Guess higher."),
            Ordering::Greater => println!("Guess lower."),
            Ordering::Equal   => {
                println!("You win!");
                return
            },
        }
    }
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;

#[macro_use]
extern crate nickel;
#[macro_use]
extern crate serde_derive;

extern crate bincode;
extern crate leveldb;

use bincode::{serialize, deserialize, Infinite};

use std::path::Path;
use std::sync::Arc;

use leveldb::database::Database;
use leveldb::kv::KV;
use leveldb::iterator::Iterable;
use leveldb::options::{Options,WriteOptions,ReadOptions};

use nickel::{Nickel, HttpRouter};
use nickel::status::StatusCode;

mod raw_body;
use self::raw_body::*;

const DEFAULT_DIR: &'static str = "./tokendb";

#[derive(Serialize, Deserialize)]
pub struct SSDeposit {
    status: String,
    address: String,
    params: Vec<String>,
    id: usize,
}

fn main() {
    let mut server = Nickel::new();

    let path = Path::new(DEFAULT_DIR);
    let db = Arc::new(TokenDB::new(path));
    let read_db = db.clone();

    server.post("/", middleware! { |req, res|
        let raw = req.raw_body();
        let deposit = serde_json::from_str::<SSDeposit>(&raw).unwrap();
        db.write_deposit(&deposit);

        format!("Deposit Received {} {}", deposit.address, deposit.status)
    });

    server.get("/:id", middleware! { |req|
        let id = req.param("id").unwrap();
        println!("id: {}", id);
        let key: i32 = id.parse()
                    .expect("Should be i32");

        let data = read_db.read_deposit(key).unwrap();
        let deposit: SSDeposit = deserialize(&data).unwrap();
        match serde_json::to_string(&deposit) {
            Ok(res) => { (StatusCode::Ok, res.to_string()) },
            Err(e) => { (StatusCode::ImATeapot, e.to_string()) }
        }
    });

    server.get("/all", middleware! { |req|
        let id = req.param("id").unwrap();
        println!("id: {}", id);
        let key: i32 = id.parse()
                    .expect("Failed to parse key");

        let data = read_db.read_deposit(key)
            .expect("Failed to lookup key");

        let deposit: SSDeposit = deserialize(&data)
            .expect("Corrupted entry in db");

        match serde_json::to_string(&deposit) {
            Ok(res) => { (StatusCode::Ok, res.to_string()) },
            Err(e) => { (StatusCode::ImATeapot, e.to_string()) }
        }
    });

    server.listen("127.0.0.1:8675");

}

pub struct TokenDB {
  db: Database<i32>
}

impl TokenDB {
  pub fn new(path: &Path) -> TokenDB {
      let mut options = Options::new();
      options.create_if_missing = true;
      let db = match Database::open(path, options) {
        Ok(db) => { db },
        Err(e) => { panic!("failed to open database: {:?}", e) }
      };
      TokenDB {
        db: db,
      }
  }

  pub fn write_deposit(&self, deposit: &SSDeposit) -> () {
      let write_opts = WriteOptions::new();
      // turn into buffer
      let bytes: Vec<u8> = serialize(deposit, Infinite).unwrap();
      match self.db.put(write_opts, deposit.id as i32, &bytes) {
          Ok(_) => { () },
          Err(e) => { panic!("failed to write to database: {:?}", e) }
      };
  }

  pub fn read_deposit(&self, key: i32) -> Option<Vec<u8>> {
      let read_opts = ReadOptions::new();
      let res = self.db.get(read_opts, key);
      let data = match res {
        Ok(data) => { data },
        Err(e) => { panic!("failed reading data: {:?}", e) }
      };
      data
  }

}
<commit_msg>db dump<commit_after>extern crate serde;
extern crate serde_json;

#[macro_use]
extern crate nickel;
#[macro_use]
extern crate serde_derive;

extern crate bincode;
extern crate leveldb;

use bincode::{serialize, deserialize, Infinite};

use std::path::Path;
use std::sync::Arc;

use leveldb::database::Database;
use leveldb::kv::KV;
use leveldb::iterator::Iterable;
use leveldb::options::{Options,WriteOptions,ReadOptions};

use nickel::{Nickel, HttpRouter, NickelError, Request, Action};
use nickel::status::StatusCode;

mod raw_body;
use self::raw_body::*;

const DEFAULT_DIR: &'static str = "./tokendb";

#[derive(Serialize, Deserialize)]
pub struct SSDeposit {
    status: String,
    address: String,
    params: Vec<String>,
    id: usize,
}

fn main() {
    let mut server = Nickel::new();

    let path = Path::new(DEFAULT_DIR);
    let db = Arc::new(TokenDB::new(path));
    let read_db = db.clone();
    let all_db = db.clone();

    server.post("/", middleware! { |req, res|
        let raw = req.raw_body();
        let deposit = serde_json::from_str::<SSDeposit>(&raw).unwrap();
        db.write_deposit(&deposit);

        format!("Deposit Received {} {}", deposit.address, deposit.status)
    });

    server.get("/key/:id", middleware! { |req|
        let id = req.param("id").unwrap();
        println!("id: {}", id);
        let key: i32 = id.parse()
                    .expect("Failed to parse key");

        let data = read_db.read_deposit(key)
            .expect("Failed to lookup key");

        let deposit: SSDeposit = deserialize(&data)
            .expect("Corrupted entry in db");

        match serde_json::to_string(&deposit) {
            Ok(res) => { (StatusCode::Ok, res.to_string()) },
            Err(e) => { (StatusCode::NotFound, e.to_string()) }
        }
    });

    server.get("/all", middleware! { |req|
        let mut last: Option<usize> = None;
        loop {
            match all_db.dump() {
                Some(data) => {
                    let deposit: SSDeposit = deserialize(&data)
                                    .expect("Corrupted entry in db");
                    if Some(deposit.id) == last {
                        break;
                    }
                    last = Some(deposit.id);
                    println!("{}", serde_json::to_string(&deposit).unwrap());
                },
                _ => { break; }
            };
        }

    });

    server.listen("127.0.0.1:8675");

}

pub struct TokenDB {
  db: Database<i32>
}

impl TokenDB {
  pub fn new(path: &Path) -> TokenDB {
      let mut options = Options::new();
      options.create_if_missing = true;
      let db = match Database::open(path, options) {
        Ok(db) => { db },
        Err(e) => { panic!("failed to open database: {:?}", e) }
      };
      TokenDB {
        db: db,
      }
  }

  pub fn write_deposit(&self, deposit: &SSDeposit) -> () {
      let write_opts = WriteOptions::new();
      // turn into buffer
      let bytes: Vec<u8> = serialize(deposit, Infinite).unwrap();
      match self.db.put(write_opts, deposit.id as i32, &bytes) {
          Ok(_) => { () },
          Err(e) => { panic!("failed to write to database: {:?}", e) }
      };
  }

  pub fn read_deposit(&self, key: i32) -> Option<Vec<u8>> {
      let read_opts = ReadOptions::new();
      let res = self.db.get(read_opts, key);
      let data = match res {
        Ok(data) => { data },
        Err(e) => { panic!("failed reading data: {:?}", e) }
      };
      data
  }

  pub fn dump(&self) -> Option<Vec<u8>> {
      let read_opts = ReadOptions::new();
      let mut iter = self.db.value_iter(read_opts);
      let data = iter.next();
      data
  }

}
<|endoftext|>


<commit_before>//! A simple first program in rust, actually I plan to do something even
//! useful. Trying to find all my audiobooks on many machines, identify them,
//! find duplicates (later trying to solve the problem, also including their permissions, different names, but same albums, etc),
//! get all stats about it).
//! It acts as a wrapper around adbflib, which holds major parts of the implemention.
extern crate adbflib;
extern crate rayon;

use async_std::task;
use crossbeam::{channel::unbounded, sync::WaitGroup};
use log::{error, info, trace, warn};
use rayon::prelude::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
use std::{
    io::{self, Error},
    path::Path, // path, clear
    sync::{
        self,
        mpsc::{channel, Sender},
        Arc, Mutex,
    },
};

use adbflib::{
    command_line,
    ctrl::{CollectionPathAlive, Ctrl, ForwardNetMessage, NetMessages, Status, UiUpdateMsg},
    data::{self, ipc::IPC, Collection},
    logit,
    net::{key_keeper, Net},
};

fn main() -> io::Result<()> {
    // get start values from the input parser!!!
    let (ui_paths, has_tui, has_webui, has_net, keep_alive, open_browser, web_port, has_ui) =
        command_line::get_start_values();

    // clone as ro
    let ui_path_ro = ui_paths.clone();

    // rayon threads for heavy cpu usage for fast results in collection search
    let max_threads = rayon::current_num_threads();

    // for synced start of different threads
    let wait_collector = WaitGroup::new();
    let wait_ui = wait_collector.clone();
    let wait_net = wait_collector.clone();

    //
    // prepare the message system
    //
    let (tx, rx) = channel::<UiUpdateMsg>();

    // these will be taken directly
    let tx_net = tx.clone();

    // for now this will stay wrapped
    let tx_from_collector_to_ui = Arc::new(Mutex::new(tx.clone()));

    // start the logging
    logit::Logit::init(logit::Log::File);

    // all optional components are wrapped into threads
    // 1 - UI         ui_thread   (optional)
    // 2 - Net        net_thread  (optional)
    // 3 - Collector  no thread yet (uses multiple rayon worker threads)
    let ui_thread = std::thread::Builder::new()
        .name("ui".into())
        .spawn(move || {
            if has_ui {
                Ctrl::run(
                    key_keeper::get_p2p_server_id(),
                    &ui_path_ro,
                    rx,
                    has_net,
                    wait_ui,
                    has_webui,
                    has_tui,
                    open_browser,
                    web_port,
                )
            } else {
                info!("no ui was created!");
                drop(wait_ui);
                Ok::<(), Error>(())
            }
        });

    let (ipc_send, ipc_receive) = unbounded::<IPC>();

    // 2 - Net Future
    let net_thread = std::thread::Builder::new()
        .name("net".into())
        .spawn(move || {
            if has_net {
                task::block_on(async move {
                    // This thread will not end itself
                    // - can be terminated by ui message
                    // - collector finished (depending on definition)

                    info!("net started!!");
                    let net_system_messages = tx_net;
                    let mut network = Net::new(has_ui, net_system_messages);

                    // startup net synchronization
                    wait_net.wait();

                    network.lookup(ipc_receive).await;
                    info!("net finished!!");
                    Ok::<(), Error>(())
                })
            } else {
                info!("no net!");
                drop(wait_net);
                Ok::<(), Error>(())
            }
        });

    // the collector ... still a problem with threading and parse_args
    // borrowing?? but since rayon is used, using a separate thread is not really
    // important
    // but yet this simple bracket to enclose this a little
    {
        trace!("syncing with 2 other threads");
        wait_collector.wait();
        trace!("sync with net and ui done ... collector can start");

        let synced_to_ui_messages = tx_from_collector_to_ui.clone();

        // start the parallel search threads with rayon, each path its own
        let init_collection = Collection::new(&key_keeper::get_p2p_server_id(), max_threads);
        let collection_protected = sync::Arc::new(sync::Mutex::new(init_collection));

        let all_collection_data =
            sync::Arc::new(sync::Mutex::new(CollectionData { nr_found_songs: 0 }));

        &ui_paths.par_iter().enumerate().for_each(|(index, elem)| {
            let sender_loop = synced_to_ui_messages.clone();
            let collection_data_in_iterator = collection_protected.clone();
            let single_path_collection_data = search_in_single_path(
                has_ui,
                collection_data_in_iterator,
                sender_loop,
                index,
                elem,
            );
            // short lock to accumulate data
            {
                all_collection_data.lock().unwrap().nr_found_songs +=
                    single_path_collection_data.nr_found_songs;
            }
        });

        info!("collector finished!!");
        if !has_ui {
            collection_protected
                .lock()
                .and_then(|locked_collection| Ok(locked_collection.print_stats()))
                .unwrap_or(())
        }
        if has_net {
            let to_send = all_collection_data.lock().unwrap().nr_found_songs;
            ipc_send
                .send(IPC::DoneSearching(to_send))
                .unwrap_or_else(|_| {
                    error!("net has to be up and receiving this send!");
                });
        }
    }

    // look for keeping alive argument if that was chosen
    if keep_alive {
        ui_thread
            .and_then(|running_thread| Ok(running_thread.join()))
            .unwrap_or_else(|_| {
                // it doesn't matter because we will terminate anyway
                error!("this should be result of ui thread!!");
                Ok(Ok(()))
            })
            .unwrap_or_else(|_| {
                // it doesn't matter because we will terminate anyway
                error!("is this normal when joining ui thread???");
                Ok(())
            })
            .unwrap();
        if has_ui {
            info!("Stopped ui thread");
        }
        // net thread
        if has_ui {
            // if had a ui , net_thread will stop also after ui quit
            drop(net_thread);
        } else {
            // if didn't have ui, net_thread will continue running
            net_thread
                .and_then(|running_thread| Ok(running_thread.join()))
                .unwrap_or_else(|_| {
                    // it doesn't matter because we will terminate anyway
                    error!("is this normal when joining net thread???");
                    Ok(Ok(()))
                })
                // todo: honestly ... fix this here!!!!!! unwrap TWICE!!!
                .unwrap()
                .unwrap();
            info!("Stopped net thread");
        }
    } else {
        drop(net_thread);
        drop(ui_thread);
    }
    Ok(())
}

// todo: move all below into data module
struct CollectionData {
    nr_found_songs: u32,
}

fn search_in_single_path(
    has_ui: bool,
    collection_protected: sync::Arc<sync::Mutex<Collection>>,
    mutex_to_ui_msg: sync::Arc<sync::Mutex<Sender<UiUpdateMsg>>>,
    index: usize,
    elem: &str,
) -> CollectionData {
    if !has_ui {
        println!("[{:?}] looking into path {:?}", index, elem);
    } else {
        // send start animation for that path
        mutex_to_ui_msg
            .lock()
            .and_then(|locked_to_start_ui_message| {
                trace!("send startAnimation for path {:?}", index);
                locked_to_start_ui_message
                    .send(UiUpdateMsg::CollectionUpdate(
                        CollectionPathAlive::BusyPath(index),
                        Status::ON,
                    ))
                    .unwrap_or_else(|_| warn!("... lost start animation for index {:?}", index));
                trace!("start busy animation");
                Ok(())
            })
            .unwrap_or_else(|_| error!("... that should not happen here at start"));
    }
    let locked_collection = &mut *collection_protected.lock().unwrap();

    // do it: main task here is to visit and dive deep
    //        into the subfolders of this folder
    match locked_collection.visit_path(Path::new(elem), &data::Collection::visit_files) {
        Ok(local_stats) => {
            if has_ui {
                // send stop animation for that path
                trace!("send stopAnimation for path {:?}", index);
                mutex_to_ui_msg
                    .lock()
                    .and_then(|locked_to_stop_ui_message| {
                        locked_to_stop_ui_message
                            .send(UiUpdateMsg::CollectionUpdate(
                                CollectionPathAlive::BusyPath(index),
                                Status::OFF,
                            ))
                            .unwrap_or_else(|_| warn!("... lost stop animation for {:?}", index));
                        trace!("stop busy animation");
                        Ok(())
                    })
                    .unwrap_or_else(|_| {
                        error!("... that should not happen here at stop");
                    });
            } else {
                let text = format!(
                    "\n\
                             analyzed: {an:>width$}, faulty: {fa:>width$}\n\
                             searched: {se:>width$}, other: {ot:>width$}",
                    an = local_stats.analyzed,
                    fa = local_stats.faulty,
                    se = local_stats.searched,
                    ot = local_stats.other,
                    width = 3
                );
                println!("[{:?}] done {}", index, text);
            }
            // return this here
            CollectionData {
                nr_found_songs: local_stats.analyzed,
            }
        }
        Err(_e) => {
            let text = format!("An error has occurred in search path [{}]!!", index);
            if has_ui {
                mutex_to_ui_msg
                    .lock()
                    .and_then(|locked_update_message| {
                        locked_update_message
                            .send(UiUpdateMsg::NetUpdate(ForwardNetMessage::Stats(
                                NetMessages::Debug(text),
                            )))
                            .unwrap();
                        Ok(())
                    })
                    .unwrap();
            } else {
                println!("{:?}", text);
            }
            // return this here
            CollectionData { nr_found_songs: 0 }
        }
    }
}
<commit_msg>[fix] better user experience when net thread is kept running<commit_after>//! A simple first program in rust, actually I plan to do something even
//! useful. Trying to find all my audiobooks on many machines, identify them,
//! find duplicates (later trying to solve the problem, also including their permissions, different names, but same albums, etc),
//! get all stats about it).
//! It acts as a wrapper around adbflib, which holds major parts of the implemention.
extern crate adbflib;
extern crate rayon;

use async_std::task;
use crossbeam::{channel::unbounded, sync::WaitGroup};
use log::{error, info, trace, warn};
use rayon::prelude::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
use std::{
    io::{self, Error},
    path::Path, // path, clear
    sync::{
        self,
        mpsc::{channel, Sender},
        Arc, Mutex,
    },
};

use adbflib::{
    command_line,
    ctrl::{CollectionPathAlive, Ctrl, ForwardNetMessage, NetMessages, Status, UiUpdateMsg},
    data::{self, ipc::IPC, Collection},
    logit,
    net::{key_keeper, Net},
};

fn main() -> io::Result<()> {
    // get start values from the input parser!!!
    let (ui_paths, has_tui, has_webui, has_net, keep_alive, open_browser, web_port, has_ui) =
        command_line::get_start_values();

    // clone as ro
    let ui_path_ro = ui_paths.clone();

    // rayon threads for heavy cpu usage for fast results in collection search
    let max_threads = rayon::current_num_threads();

    // for synced start of different threads
    let wait_collector = WaitGroup::new();
    let wait_ui = wait_collector.clone();
    let wait_net = wait_collector.clone();

    //
    // prepare the message system
    //
    let (tx, rx) = channel::<UiUpdateMsg>();

    // these will be taken directly
    let tx_net = tx.clone();

    // for now this will stay wrapped
    let tx_from_collector_to_ui = Arc::new(Mutex::new(tx.clone()));

    // start the logging
    logit::Logit::init(logit::Log::File);

    // all optional components are wrapped into threads
    // 1 - UI         ui_thread   (optional)
    // 2 - Net        net_thread  (optional)
    // 3 - Collector  no thread yet (uses multiple rayon worker threads)
    let ui_thread = std::thread::Builder::new()
        .name("ui".into())
        .spawn(move || {
            if has_ui {
                Ctrl::run(
                    key_keeper::get_p2p_server_id(),
                    &ui_path_ro,
                    rx,
                    has_net,
                    wait_ui,
                    has_webui,
                    has_tui,
                    open_browser,
                    web_port,
                )
            } else {
                info!("no ui was created!");
                drop(wait_ui);
                Ok::<(), Error>(())
            }
        });

    let (ipc_send, ipc_receive) = unbounded::<IPC>();

    // 2 - Net Future
    let net_thread = std::thread::Builder::new()
        .name("net".into())
        .spawn(move || {
            if has_net {
                task::block_on(async move {
                    // This thread will not end itself
                    // - can be terminated by ui message
                    // - collector finished (depending on definition)

                    info!("net started!!");
                    let net_system_messages = tx_net;
                    let mut network = Net::new(has_ui, net_system_messages);

                    // startup net synchronization
                    wait_net.wait();

                    network.lookup(ipc_receive).await;
                    info!("net finished!!");
                    Ok::<(), Error>(())
                })
            } else {
                info!("no net!");
                drop(wait_net);
                Ok::<(), Error>(())
            }
        });

    // the collector ... still a problem with threading and parse_args
    // borrowing?? but since rayon is used, using a separate thread is not really
    // important
    // but yet this simple bracket to enclose this a little
    {
        trace!("syncing with 2 other threads");
        wait_collector.wait();
        trace!("sync with net and ui done ... collector can start");

        let synced_to_ui_messages = tx_from_collector_to_ui.clone();

        // start the parallel search threads with rayon, each path its own
        let init_collection = Collection::new(&key_keeper::get_p2p_server_id(), max_threads);
        let collection_protected = sync::Arc::new(sync::Mutex::new(init_collection));

        let all_collection_data =
            sync::Arc::new(sync::Mutex::new(CollectionData { nr_found_songs: 0 }));

        &ui_paths.par_iter().enumerate().for_each(|(index, elem)| {
            let sender_loop = synced_to_ui_messages.clone();
            let collection_data_in_iterator = collection_protected.clone();
            let single_path_collection_data = search_in_single_path(
                has_ui,
                collection_data_in_iterator,
                sender_loop,
                index,
                elem,
            );
            // short lock to accumulate data
            {
                all_collection_data.lock().unwrap().nr_found_songs +=
                    single_path_collection_data.nr_found_songs;
            }
        });

        info!("collector finished!!");
        if !has_ui {
            collection_protected
                .lock()
                .and_then(|locked_collection| Ok(locked_collection.print_stats()))
                .unwrap_or(())
        }
        if has_net {
            let to_send = all_collection_data.lock().unwrap().nr_found_songs;
            ipc_send
                .send(IPC::DoneSearching(to_send))
                .unwrap_or_else(|_| {
                    error!("net has to be up and receiving this send!");
                });
        }
    }

    // look for keeping alive argument if that was chosen
    if keep_alive {
        ui_thread
            .and_then(|running_thread| Ok(running_thread.join()))
            .unwrap_or_else(|_| {
                // it doesn't matter because we will terminate anyway
                error!("this should be result of ui thread!!");
                Ok(Ok(()))
            })
            .unwrap_or_else(|_| {
                // it doesn't matter because we will terminate anyway
                error!("is this normal when joining ui thread???");
                Ok(())
            })
            .unwrap();
        if has_ui {
            info!("Stopped ui thread");
        }
        // net thread
        if has_ui {
            // if had a ui , net_thread will stop also after ui quit
            drop(net_thread);
        } else {
            // if didn't have ui, net_thread will continue running
            println!(
                "Search is finished, but net thread is kept running!\nTo stop send break command (ctrl-c)!"
            );
            net_thread
                .and_then(|running_thread| Ok(running_thread.join()))
                .unwrap_or_else(|_| {
                    // it doesn't matter because we will terminate anyway
                    error!("is this normal when joining net thread???");
                    Ok(Ok(()))
                })
                // todo: honestly ... fix this here!!!!!! unwrap TWICE!!!
                .unwrap()
                .unwrap();
            info!("Stopped net thread");
        }
    } else {
        drop(net_thread);
        drop(ui_thread);
    }
    Ok(())
}

// todo: move all below into data module
struct CollectionData {
    nr_found_songs: u32,
}

fn search_in_single_path(
    has_ui: bool,
    collection_protected: sync::Arc<sync::Mutex<Collection>>,
    mutex_to_ui_msg: sync::Arc<sync::Mutex<Sender<UiUpdateMsg>>>,
    index: usize,
    elem: &str,
) -> CollectionData {
    if !has_ui {
        println!("[{:?}] looking into path {:?}", index, elem);
    } else {
        // send start animation for that path
        mutex_to_ui_msg
            .lock()
            .and_then(|locked_to_start_ui_message| {
                trace!("send startAnimation for path {:?}", index);
                locked_to_start_ui_message
                    .send(UiUpdateMsg::CollectionUpdate(
                        CollectionPathAlive::BusyPath(index),
                        Status::ON,
                    ))
                    .unwrap_or_else(|_| warn!("... lost start animation for index {:?}", index));
                trace!("start busy animation");
                Ok(())
            })
            .unwrap_or_else(|_| error!("... that should not happen here at start"));
    }
    let locked_collection = &mut *collection_protected.lock().unwrap();

    // do it: main task here is to visit and dive deep
    //        into the subfolders of this folder
    match locked_collection.visit_path(Path::new(elem), &data::Collection::visit_files) {
        Ok(local_stats) => {
            if has_ui {
                // send stop animation for that path
                trace!("send stopAnimation for path {:?}", index);
                mutex_to_ui_msg
                    .lock()
                    .and_then(|locked_to_stop_ui_message| {
                        locked_to_stop_ui_message
                            .send(UiUpdateMsg::CollectionUpdate(
                                CollectionPathAlive::BusyPath(index),
                                Status::OFF,
                            ))
                            .unwrap_or_else(|_| warn!("... lost stop animation for {:?}", index));
                        trace!("stop busy animation");
                        Ok(())
                    })
                    .unwrap_or_else(|_| {
                        error!("... that should not happen here at stop");
                    });
            } else {
                let text = format!(
                    "\n\
                             analyzed: {an:>width$}, faulty: {fa:>width$}\n\
                             searched: {se:>width$}, other: {ot:>width$}",
                    an = local_stats.analyzed,
                    fa = local_stats.faulty,
                    se = local_stats.searched,
                    ot = local_stats.other,
                    width = 3
                );
                println!("[{:?}] done {}", index, text);
            }
            // return this here
            CollectionData {
                nr_found_songs: local_stats.analyzed,
            }
        }
        Err(_e) => {
            let text = format!("An error has occurred in search path [{}]!!", index);
            if has_ui {
                mutex_to_ui_msg
                    .lock()
                    .and_then(|locked_update_message| {
                        locked_update_message
                            .send(UiUpdateMsg::NetUpdate(ForwardNetMessage::Stats(
                                NetMessages::Debug(text),
                            )))
                            .unwrap();
                        Ok(())
                    })
                    .unwrap();
            } else {
                println!("{:?}", text);
            }
            // return this here
            CollectionData { nr_found_songs: 0 }
        }
    }
}
<|endoftext|>