<commit_before>#![allow(dead_code)]

use std::ptr::null;
use std::c_str::CString;
use std::os::{errno, error_string};
use libc::{c_int, c_char, c_ulong, pid_t};
use libc::funcs::posix88::unistd::fork;

// errno.h
static EINTR: int = 4;

// sched.h
static CLONE_NEWNS: c_int = 0x00020000;   /* Set to create new namespace.  */
static CLONE_NEWUTS: c_int = 0x04000000;  /* New utsname group.  */
static CLONE_NEWIPC: c_int = 0x08000000;  /* New ipcs.  */
static CLONE_NEWUSER: c_int = 0x10000000; /* New user namespace.  */
static CLONE_NEWPID: c_int = 0x20000000;  /* New pid namespace.  */
static CLONE_NEWNET: c_int = 0x40000000;  /* New network namespace.  */

// sys/mount.h
static MS_RDONLY: c_ulong = 1;                /* Mount read-only.  */
static MS_NOSUID: c_ulong = 2;                /* Ignore suid and sgid bits.  */
static MS_NODEV: c_ulong = 4;                 /* Disallow access to device special files.  */
static MS_NOEXEC: c_ulong = 8;                /* Disallow program execution.  */
static MS_SYNCHRONOUS: c_ulong = 16;          /* Writes are synced at once.  */
static MS_REMOUNT: c_ulong = 32;              /* Alter flags of a mounted FS.  */
static MS_MANDLOCK: c_ulong = 64;             /* Allow mandatory locks on an FS.  */
static MS_DIRSYNC: c_ulong = 128;             /* Directory modifications are synchronous.  */
static MS_NOATIME: c_ulong = 1024;            /* Do not update access times.  */
static MS_NODIRATIME: c_ulong = 2048;         /* Do not update directory access times.  */
static MS_BIND: c_ulong = 4096;               /* Bind directory at different place.  */
static MS_MOVE: c_ulong = 8192;
static MS_REC: c_ulong = 16384;
static MS_SILENT: c_ulong = 32768;
static MS_POSIXACL: c_ulong = 1 << 16;        /* VFS does not apply the umask.  */
static MS_UNBINDABLE: c_ulong = 1 << 17;      /* Change to unbindable.  */
static MS_PRIVATE: c_ulong = 1 << 18;         /* Change to private.  */
static MS_SLAVE: c_ulong = 1 << 19;           /* Change to slave.  */
static MS_SHARED: c_ulong = 1 << 20;          /* Change to shared.  */
static MS_RELATIME: c_ulong = 1 << 21;        /* Update atime relative to mtime/ctime.  */
static MS_KERNMOUNT: c_ulong = 1 << 22;       /* This is a kern_mount call.  */
static MS_I_VERSION: c_ulong =  1 << 23;      /* Update inode I_version field.  */
static MS_STRICTATIME: c_ulong = 1 << 24;     /* Always perform atime updates.  */
static MS_ACTIVE: c_ulong = 1 << 30;
static MS_NOUSER: c_ulong = 1 << 31;

extern  {
    // sched.h
    fn unshare(flags: c_int) -> c_int;

    // unistd.h
    fn chroot(dir: *c_char) -> c_int;
    fn execve(filename: *c_char, argv: **c_char, envp: **c_char) -> c_int;

    // sys/types.h
    // sys/wait.h
    fn waitpid(pid: pid_t, status: *c_int, options: c_int) -> pid_t;

    // sys/mount.h
    fn mount(source: *c_char, target: *c_char,
        filesystemtype: *c_char, flags: c_ulong,
        data: *c_char) -> c_int;

}

pub fn make_namespace() -> Result<(), String> {
    let rc = unsafe {
        unshare(CLONE_NEWNS|CLONE_NEWIPC|CLONE_NEWUSER|CLONE_NEWPID)
    };
    if rc != 0 {
        return Err(format!("Error making namespace: {}",
            error_string(errno() as uint)));
    }
    return Ok(());
}

pub fn change_root(root: &Path) -> Result<(), String> {
    debug!("Chrooting into {}", root.display());
    let rc = root.with_c_str(|root| unsafe { chroot(root) });
    if rc != 0 {
        return Err(format!("Error changing root: {}",
            error_string(errno() as uint)));
    }
    return Ok(());
}

pub fn bind_mount(source: &Path, target: &Path, read_write: bool)
    -> Result<(), String>
{
    debug!("Mounting {} into {}{}",
        source.display(), target.display(), if read_write {""} else {" (ro)"});
    let mut flags = MS_BIND|MS_REC;
    if !read_write {
        flags |= MS_RDONLY;
    }
    let rc = unsafe {
        source.with_c_str(|source|
        target.with_c_str(|target|
            mount(source, target, null(), flags, null())
        ))};
    if rc != 0 {
        return Err(format!("Error mounting {}: {}",
            target.display(), error_string(errno() as uint)));
    }
    Ok(())
}

pub fn mount_pseudofs(fstype: &str, target: &Path, fsoptions: &str)
    -> Result<(), String>
{
    debug!("Mounting {} as {} with options: {}",
        target.display(), fstype, fsoptions);
    let flags = MS_NOSUID|MS_NODEV;
    let rc = unsafe {
        fstype.with_c_str(|fstype|
        target.with_c_str(|target|
        fsoptions.with_c_str(|fsoptions|
            mount(fstype, target, fstype, flags, fsoptions)
        )))};
    if rc != 0 {
        return Err(format!("Error mounting {}: {}",
            target.display(), error_string(errno() as uint)));
    }
    Ok(())
}

pub fn execute(command: &String, args: &Vec<String>, environ: &Vec<String>)
    -> Result <(), String>
{
    debug!("Executing {} with args: {} with environ: {}",
        command, args, environ);
    let mut cargs: Vec<CString> = args.iter()
        .map(|s| { s.to_c_str() }).collect();
    cargs.insert(0, command.to_c_str());
    let cenviron: Vec<CString> = environ.iter()
        .map(|s| { s.to_c_str() }).collect();
    unsafe {
        let mut argv: Vec<*c_char> =
            cargs.move_iter().map(|s| s.with_ref(|p| p)).collect();
        argv.push(null());
        let mut envp: Vec<*c_char> =
            cenviron.move_iter().map(|s| s.with_ref(|p| p)).collect();
        envp.push(null());
        // TODO(tailhook) chdir
        command.with_c_str(|command|
            execve(
                command,
                argv.as_ptr(),
                envp.as_ptr(),
                ));
    }
    return Err(format!("Error executing command {}: {}",
        command, error_string(errno() as uint)));
}

pub fn forkme() -> Result<pid_t, String> {
    debug!("Forking");
    let rc = unsafe { fork() };
    if rc == -1 {
        return Err(format!("Error forking: {}",
            error_string(errno() as uint)));
    }
    return Ok(rc);
}

pub fn wait_process(pid: pid_t) -> Result<int, String> {
    loop {
        let status = 0;
        let rc = unsafe { waitpid(pid, &status, 0) };
        if rc < 0 {
            if errno() == EINTR {
                continue;
            } else {
                return Err(format!("Error waiting for child: {}",
                    error_string(errno() as uint)));
            }
        }
        return Ok(rc as int);
    }
}
<commit_msg>Fix bug in passing environ to children<commit_after>#![allow(dead_code)]

use std::ptr::null;
use std::c_str::CString;
use std::os::{errno, error_string};
use libc::{c_int, c_char, c_ulong, pid_t};
use libc::funcs::posix88::unistd::fork;

// errno.h
static EINTR: int = 4;

// sched.h
static CLONE_NEWNS: c_int = 0x00020000;   /* Set to create new namespace.  */
static CLONE_NEWUTS: c_int = 0x04000000;  /* New utsname group.  */
static CLONE_NEWIPC: c_int = 0x08000000;  /* New ipcs.  */
static CLONE_NEWUSER: c_int = 0x10000000; /* New user namespace.  */
static CLONE_NEWPID: c_int = 0x20000000;  /* New pid namespace.  */
static CLONE_NEWNET: c_int = 0x40000000;  /* New network namespace.  */

// sys/mount.h
static MS_RDONLY: c_ulong = 1;                /* Mount read-only.  */
static MS_NOSUID: c_ulong = 2;                /* Ignore suid and sgid bits.  */
static MS_NODEV: c_ulong = 4;                 /* Disallow access to device special files.  */
static MS_NOEXEC: c_ulong = 8;                /* Disallow program execution.  */
static MS_SYNCHRONOUS: c_ulong = 16;          /* Writes are synced at once.  */
static MS_REMOUNT: c_ulong = 32;              /* Alter flags of a mounted FS.  */
static MS_MANDLOCK: c_ulong = 64;             /* Allow mandatory locks on an FS.  */
static MS_DIRSYNC: c_ulong = 128;             /* Directory modifications are synchronous.  */
static MS_NOATIME: c_ulong = 1024;            /* Do not update access times.  */
static MS_NODIRATIME: c_ulong = 2048;         /* Do not update directory access times.  */
static MS_BIND: c_ulong = 4096;               /* Bind directory at different place.  */
static MS_MOVE: c_ulong = 8192;
static MS_REC: c_ulong = 16384;
static MS_SILENT: c_ulong = 32768;
static MS_POSIXACL: c_ulong = 1 << 16;        /* VFS does not apply the umask.  */
static MS_UNBINDABLE: c_ulong = 1 << 17;      /* Change to unbindable.  */
static MS_PRIVATE: c_ulong = 1 << 18;         /* Change to private.  */
static MS_SLAVE: c_ulong = 1 << 19;           /* Change to slave.  */
static MS_SHARED: c_ulong = 1 << 20;          /* Change to shared.  */
static MS_RELATIME: c_ulong = 1 << 21;        /* Update atime relative to mtime/ctime.  */
static MS_KERNMOUNT: c_ulong = 1 << 22;       /* This is a kern_mount call.  */
static MS_I_VERSION: c_ulong =  1 << 23;      /* Update inode I_version field.  */
static MS_STRICTATIME: c_ulong = 1 << 24;     /* Always perform atime updates.  */
static MS_ACTIVE: c_ulong = 1 << 30;
static MS_NOUSER: c_ulong = 1 << 31;

extern  {
    // sched.h
    fn unshare(flags: c_int) -> c_int;

    // unistd.h
    fn chroot(dir: *c_char) -> c_int;
    fn execve(filename: *c_char, argv: **c_char, envp: **c_char) -> c_int;

    // sys/types.h
    // sys/wait.h
    fn waitpid(pid: pid_t, status: *c_int, options: c_int) -> pid_t;

    // sys/mount.h
    fn mount(source: *c_char, target: *c_char,
        filesystemtype: *c_char, flags: c_ulong,
        data: *c_char) -> c_int;

}

pub fn make_namespace() -> Result<(), String> {
    let rc = unsafe {
        unshare(CLONE_NEWNS|CLONE_NEWIPC|CLONE_NEWUSER|CLONE_NEWPID)
    };
    if rc != 0 {
        return Err(format!("Error making namespace: {}",
            error_string(errno() as uint)));
    }
    return Ok(());
}

pub fn change_root(root: &Path) -> Result<(), String> {
    debug!("Chrooting into {}", root.display());
    let rc = root.with_c_str(|root| unsafe { chroot(root) });
    if rc != 0 {
        return Err(format!("Error changing root: {}",
            error_string(errno() as uint)));
    }
    return Ok(());
}

pub fn bind_mount(source: &Path, target: &Path, read_write: bool)
    -> Result<(), String>
{
    debug!("Mounting {} into {}{}",
        source.display(), target.display(), if read_write {""} else {" (ro)"});
    let mut flags = MS_BIND|MS_REC;
    if !read_write {
        flags |= MS_RDONLY;
    }
    let rc = unsafe {
        source.with_c_str(|source|
        target.with_c_str(|target|
            mount(source, target, null(), flags, null())
        ))};
    if rc != 0 {
        return Err(format!("Error mounting {}: {}",
            target.display(), error_string(errno() as uint)));
    }
    Ok(())
}

pub fn mount_pseudofs(fstype: &str, target: &Path, fsoptions: &str)
    -> Result<(), String>
{
    debug!("Mounting {} as {} with options: {}",
        target.display(), fstype, fsoptions);
    let flags = MS_NOSUID|MS_NODEV;
    let rc = unsafe {
        fstype.with_c_str(|fstype|
        target.with_c_str(|target|
        fsoptions.with_c_str(|fsoptions|
            mount(fstype, target, fstype, flags, fsoptions)
        )))};
    if rc != 0 {
        return Err(format!("Error mounting {}: {}",
            target.display(), error_string(errno() as uint)));
    }
    Ok(())
}

pub fn execute(command: &String, args: &Vec<String>, environ: &Vec<String>)
    -> Result <(), String>
{
    debug!("Executing {} with args: {} with environ: {}",
        command, args, environ);
    let mut cargs: Vec<CString> = args.iter()
        .map(|s| { s.to_c_str() }).collect();
    cargs.insert(0, command.to_c_str());
    let cenviron: Vec<CString> = environ.iter()
        .map(|s| s.to_c_str()).collect();
    unsafe {
        let mut argv: Vec<*c_char> =
            cargs.iter().map(|s| s.with_ref(|p| p)).collect();
        argv.push(null());
        let mut envp: Vec<*c_char> =
            cenviron.iter().map(|s| s.with_ref(|p| p)).collect();
        envp.push(null());
        // TODO(tailhook) chdir
        command.with_c_str(|command|
            execve(
                command,
                argv.as_ptr(),
                envp.as_ptr(),
                ));
    }
    return Err(format!("Error executing command {}: {}",
        command, error_string(errno() as uint)));
}

pub fn forkme() -> Result<pid_t, String> {
    debug!("Forking");
    let rc = unsafe { fork() };
    if rc == -1 {
        return Err(format!("Error forking: {}",
            error_string(errno() as uint)));
    }
    return Ok(rc);
}

pub fn wait_process(pid: pid_t) -> Result<int, String> {
    loop {
        let status = 0;
        let rc = unsafe { waitpid(pid, &status, 0) };
        if rc < 0 {
            if errno() == EINTR {
                continue;
            } else {
                return Err(format!("Error waiting for child: {}",
                    error_string(errno() as uint)));
            }
        }
        return Ok(rc as int);
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rocket_codegen)]
#![cfg_attr(test, plugin(stainless))]

extern crate uuid;
extern crate chrono;
extern crate rocket;
extern crate r2d2;
extern crate r2d2_diesel;
extern crate argon2rs;
extern crate rustc_serialize;
extern crate serde_json;
extern crate serde_yaml;
extern crate validator;
extern crate jsonwebtoken;
extern crate petgraph;

#[macro_use]
extern crate rocket_contrib;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate validator_derive;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_codegen;

pub mod schema;
pub mod validation;
pub mod models;
pub mod data;
pub mod responses;
pub mod api;
pub mod helpers;
pub mod handlers;
pub mod statics;

#[cfg(test)]
mod tests;

use data::modules::get_module_list;
use data::researches::build_research_graph;

pub fn rocket_factory() -> rocket::Rocket {
    // Check if we have valid yml and check research graph for cycles.
    get_module_list();
    build_research_graph();

    rocket::ignite()
        .manage(helpers::db::init_db_pool())
        .mount("/", routes![statics::index])
        .mount("/static", routes![statics::static_files])
        .mount("/tick/",
               routes![
               api::update::update::tick,
        ])
        .mount("/api/auth/",
               routes![
               api::auth::auth::login,
        ])
        .mount("/api/user/",
               routes![
               api::user::user::info,
               api::user::user::register,
               api::user::user::settings,
        ])
        .mount("/api/pod/",
               routes![
               api::pod::pod::settings,
        ])
        .mount("/api/queue/",
               routes![
               api::queue::pod::pod_queue_entries,
        ])

        .mount("/api/resources/",
               routes![
               api::resources::pod::pod_resources,
        ])
        .mount("/api/researches/",
               routes![
               api::research::pod::get_researches,
               api::research::pod::start_research,
               api::research::pod::stop_research,
        ])
        .mount("/api/modules/",
               routes![
               api::module::general::get_info,
               api::module::pod::get_modules,
               api::module::pod::add_module,
               api::module::pod::remove_module,
               api::module::pod::upgrade_module,
               api::module::pod::stop_module_upgrade,
        ])
        .catch(errors![handlers::bad_request_handler,
                       handlers::unauthorized_handler,
                       handlers::forbidden_handler,
                       handlers::not_found_handler,
                       handlers::internal_server_error_handler,
                       handlers::service_unavailable_handler])
}
<commit_msg>Remove slashes on rocket mount paths<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]
#![cfg_attr(test, plugin(stainless))]

extern crate uuid;
extern crate chrono;
extern crate rocket;
extern crate r2d2;
extern crate r2d2_diesel;
extern crate argon2rs;
extern crate rustc_serialize;
extern crate serde_json;
extern crate serde_yaml;
extern crate validator;
extern crate jsonwebtoken;
extern crate petgraph;

#[macro_use]
extern crate rocket_contrib;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate validator_derive;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_codegen;

pub mod schema;
pub mod validation;
pub mod models;
pub mod data;
pub mod responses;
pub mod api;
pub mod helpers;
pub mod handlers;
pub mod statics;

#[cfg(test)]
mod tests;

use data::modules::get_module_list;
use data::researches::build_research_graph;

pub fn rocket_factory() -> rocket::Rocket {
    // Check if we have valid yml and check research graph for cycles.
    get_module_list();
    build_research_graph();

    rocket::ignite()
        .manage(helpers::db::init_db_pool())
        .mount("/", routes![statics::index])
        .mount("/static", routes![statics::static_files])
        .mount("/tick",
               routes![
               api::update::update::tick,
        ])
        .mount("/api/auth",
               routes![
               api::auth::auth::login,
        ])
        .mount("/api/user",
               routes![
               api::user::user::info,
               api::user::user::register,
               api::user::user::settings,
        ])
        .mount("/api/pod",
               routes![
               api::pod::pod::settings,
        ])
        .mount("/api/queue",
               routes![
               api::queue::pod::pod_queue_entries,
        ])

        .mount("/api/resources",
               routes![
               api::resources::pod::pod_resources,
        ])
        .mount("/api/researches",
               routes![
               api::research::pod::get_researches,
               api::research::pod::start_research,
               api::research::pod::stop_research,
        ])
        .mount("/api/modules",
               routes![
               api::module::general::get_info,
               api::module::pod::get_modules,
               api::module::pod::add_module,
               api::module::pod::remove_module,
               api::module::pod::upgrade_module,
               api::module::pod::stop_module_upgrade,
        ])
        .catch(errors![handlers::bad_request_handler,
                       handlers::unauthorized_handler,
                       handlers::forbidden_handler,
                       handlers::not_found_handler,
                       handlers::internal_server_error_handler,
                       handlers::service_unavailable_handler])
}
<|endoftext|>


<commit_before>use common::interval_timer::IntervalTimer;
use time;

pub struct Sun {
  // The sun as portions of a 65536-degree circle.
  pub position: u16,
  pub timer: IntervalTimer,
  pub print_timer: IntervalTimer,
}

impl Sun {
  pub fn new(tick_ns: u64) -> Sun {
    Sun {
      position: 0,
      timer: IntervalTimer::new(tick_ns, time::precise_time_ns()),
      print_timer: IntervalTimer::new(2e9 as u64, time::precise_time_ns()),
    }
  }

  pub fn update(&mut self) -> Option<f32> {
    let ticks = self.timer.update(time::precise_time_ns());

    if ticks == 0 {
      return None;
    }

    self.position += ticks as u16;

    // Fraction completed of a full cycle.
    let fraction = (self.position as f32) / 65536.0;

    if self.print_timer.update(time::precise_time_ns()) > 0 {
      debug!("Sun is at {:.0}%.", fraction * 100.0);
    }

    Some(fraction)
  }
}
<commit_msg>Workaround for arithmetic exception when formatting f32s for logs.<commit_after>use common::interval_timer::IntervalTimer;
use time;

pub struct Sun {
  // The sun as portions of a 65536-degree circle.
  pub position: u16,
  pub timer: IntervalTimer,
  pub print_timer: IntervalTimer,
}

impl Sun {
  pub fn new(tick_ns: u64) -> Sun {
    Sun {
      position: 0,
      timer: IntervalTimer::new(tick_ns, time::precise_time_ns()),
      print_timer: IntervalTimer::new(2e9 as u64, time::precise_time_ns()),
    }
  }

  pub fn update(&mut self) -> Option<f32> {
    let ticks = self.timer.update(time::precise_time_ns());

    if ticks == 0 {
      return None;
    }

    self.position += ticks as u16;

    // Fraction completed of a full cycle.
    let fraction = (self.position as f32) / 65536.0;

    if self.print_timer.update(time::precise_time_ns()) > 0 {
      debug!("Sun is at {:.1}%.", fraction * 100.0);
    }

    Some(fraction)
  }
}
<|endoftext|>


<commit_before>use std::ptr;

use crate::graph;

struct ModuleStackFrame<'graph, 'frame> {
    parent: Option<&'frame ModuleStackFrame<'graph, 'frame>>,
    module: &'graph graph::Module<'graph>,
}

pub fn validate_module_hierarchy<'graph>(m: &'graph graph::Module<'graph>) {
    validate_module_hierarchy_impl(
        m,
        &ModuleStackFrame {
            parent: None,
            module: m,
        },
        m,
    );
}

fn validate_module_hierarchy_impl<'graph, 'frame>(
    m: &graph::Module<'graph>,
    module_stack_frame: &ModuleStackFrame<'graph, 'frame>,
    root: &graph::Module<'graph>,
) {
    for register in m.registers.borrow().iter() {
        match register.data {
            graph::SignalData::Reg { ref data } => {
                if data.next.borrow().is_none() {
                    panic!("Cannot generate code for module \"{}\" because module \"{}\" contains a register called \"{}\" which is not driven.", root.name, m.name, data.name);
                }
            }
            _ => unreachable!(),
        }
    }

    for instance in m.instances.borrow().iter() {
        let instantiated_module = instance.instantiated_module;

        if ptr::eq(instantiated_module, m) {
            panic!("Cannot generate code for module \"{}\" because it has a recursive definition formed by an instance of itself called \"{}\".", m.name, instance.name);
        }

        let mut frame = module_stack_frame;
        loop {
            if ptr::eq(instantiated_module, frame.module) {
                panic!("Cannot generate code for module \"{}\" because it has a recursive definition formed by an instance of itself called \"{}\" in module \"{}\".", root.name, instance.name, m.name);
            }

            if let Some(parent) = frame.parent {
                frame = parent;
            } else {
                break;
            }
        }

        for input_name in instantiated_module.inputs.borrow().keys() {
            if !instance.driven_inputs.borrow().contains_key(input_name) {
                panic!("Cannot generate code for module \"{}\" because module \"{}\" contains an instance of module \"{}\" called \"{}\" whose input \"{}\" is not driven.", root.name, m.name, instantiated_module.name, instance.name, input_name);
            }
        }

        validate_module_hierarchy_impl(
            instantiated_module,
            &ModuleStackFrame {
                parent: Some(module_stack_frame),
                module: instantiated_module,
            },
            root,
        );
    }
}
<commit_msg>Detect recursive module definitions and undriven registers in separate passes<commit_after>use std::ptr;

use crate::graph;

struct ModuleStackFrame<'graph, 'frame> {
    parent: Option<&'frame ModuleStackFrame<'graph, 'frame>>,
    module: &'graph graph::Module<'graph>,
}

pub fn validate_module_hierarchy<'graph>(m: &'graph graph::Module<'graph>) {
    detect_recursive_definitions(
        m,
        &ModuleStackFrame {
            parent: None,
            module: m,
        },
        m,
    );
    detect_undriven_registers(
        m,
        &ModuleStackFrame {
            parent: None,
            module: m,
        },
        m,
    );
}

fn detect_recursive_definitions<'graph, 'frame>(
    m: &graph::Module<'graph>,
    module_stack_frame: &ModuleStackFrame<'graph, 'frame>,
    root: &graph::Module<'graph>,
) {
    for instance in m.instances.borrow().iter() {
        let instantiated_module = instance.instantiated_module;

        if ptr::eq(instantiated_module, m) {
            panic!("Cannot generate code for module \"{}\" because it has a recursive definition formed by an instance of itself called \"{}\".", m.name, instance.name);
        }

        let mut frame = module_stack_frame;
        loop {
            if ptr::eq(instantiated_module, frame.module) {
                panic!("Cannot generate code for module \"{}\" because it has a recursive definition formed by an instance of itself called \"{}\" in module \"{}\".", root.name, instance.name, m.name);
            }

            if let Some(parent) = frame.parent {
                frame = parent;
            } else {
                break;
            }
        }

        for input_name in instantiated_module.inputs.borrow().keys() {
            if !instance.driven_inputs.borrow().contains_key(input_name) {
                panic!("Cannot generate code for module \"{}\" because module \"{}\" contains an instance of module \"{}\" called \"{}\" whose input \"{}\" is not driven.", root.name, m.name, instantiated_module.name, instance.name, input_name);
            }
        }

        detect_recursive_definitions(
            instantiated_module,
            &ModuleStackFrame {
                parent: Some(module_stack_frame),
                module: instantiated_module,
            },
            root,
        );
    }
}

fn detect_undriven_registers<'graph, 'frame>(
    m: &graph::Module<'graph>,
    module_stack_frame: &ModuleStackFrame<'graph, 'frame>,
    root: &graph::Module<'graph>,
) {
    for register in m.registers.borrow().iter() {
        match register.data {
            graph::SignalData::Reg { ref data } => {
                if data.next.borrow().is_none() {
                    panic!("Cannot generate code for module \"{}\" because module \"{}\" contains a register called \"{}\" which is not driven.", root.name, m.name, data.name);
                }
            }
            _ => unreachable!(),
        }
    }

    for instance in m.instances.borrow().iter() {
        let instantiated_module = instance.instantiated_module;

        detect_undriven_registers(
            instantiated_module,
            &ModuleStackFrame {
                parent: Some(module_stack_frame),
                module: instantiated_module,
            },
            root,
        );
    }
}
<|endoftext|>


<commit_before>use iron::Chain;
use shared::{ShareableMiddleware, Shared};

pub trait SharedLink {
    fn link_shared<S: ShareableMiddleware + Send + Share>(&mut self, S);
}

impl<C: Chain> SharedLink for C {
    fn link_shared<S: ShareableMiddleware + Send + Share>(&mut self, s: S) {
        self.link(Shared::new(s))
    }
}

<commit_msg>(doc) Documented SharedLink mixin.<commit_after>use iron::Chain;
use shared::{ShareableMiddleware, Shared};

/// A mixin trait for providing the `link_shared` method to `Chain`, allowing
/// for convenient additions of `ShareableMiddleware` as
/// `Middleware`.
pub trait SharedLink {
    /// Attach a `ShareableMiddleware` as a `Middleware`.
    fn link_shared<S: ShareableMiddleware + Send + Share>(&mut self, S);
}

impl<C: Chain> SharedLink for C {
    fn link_shared<S: ShareableMiddleware + Send + Share>(&mut self, s: S) {
        self.link(Shared::new(s))
    }
}

<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use autocxx_engine::parse_file;
use clap::{crate_authors, crate_version, App, Arg, SubCommand};
use indoc::indoc;
use proc_macro2::TokenStream;
use quote::ToTokens;
use std::io::Write;
use std::path::PathBuf;
use std::{fs::File, path::Path};

fn main() {
    let matches = App::new("autocxx-gen")
        .version(crate_version!())
        .author(crate_authors!())
        .about("Generates C++ files from Rust files that contain include_cpp! macros")
        .long_about(indoc! {"
                Command line utility to expand the Rust 'autocxx'
                include_cpp macro. Normal usage here is to use the gen-cpp
                subcommand to generate the .cpp and .h side of the bindings,
                such that you can build them and link them to Rust code.
                You can also use this utility
                to expand the Rust code if you wish to avoid a dependency
                on a C++ include path within your Rust build process.
        "})
        .arg(
            Arg::with_name("INPUT")
                .help("Sets the input .rs file to use")
                .required(true)
                .index(1),
        )
        .arg(
            Arg::with_name("outdir")
                .short("o")
                .long("outdir")
                .value_name("PATH")
                .help("output directory path")
                .takes_value(true)
                .required(true),
        )
        .arg(
            Arg::with_name("inc")
                .long("inc")
                .value_name("INCLUDE DIRS")
                .help("include path")
                .takes_value(true),
        )
        .subcommand(
            SubCommand::with_name("gen-cpp")
                .help("Generate C++ .cpp and .h files. Normal mode of operation.")
                .arg(
                    Arg::with_name("pattern")
                        .long("pattern")
                        .value_name("PATTERN")
                        .help(".h and .cpp output pattern")
                        .default_value("gen")
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("cpp-extension")
                        .long("cpp-extension")
                        .value_name("EXTENSION")
                        .default_value("cc")
                        .help("include path")
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("generate-exact")
                        .long("generate-exact")
                        .value_name("NUM")
                        .help("always generate this number of .cc and .h files")
                        .takes_value(true),
                ),
        )
        .subcommand(SubCommand::with_name("gen-rs").help("Generate expanded Rust file."))
        .get_matches();
    let mut parsed_file = parse_file(matches.value_of("INPUT").unwrap())
        .expect("Unable to parse Rust file and interpret autocxx macro");
    let incs = matches.value_of("inc").unwrap_or("");
    // In future, we should provide an option to write a .d file here
    // by passing a callback into the dep_recorder parameter here.
    // https://github.com/google/autocxx/issues/56
    parsed_file
        .resolve_all(incs, None)
        .expect("Unable to resolve macro");
    let outdir: PathBuf = matches.value_of_os("outdir").unwrap().into();
    if let Some(matches) = matches.subcommand_matches("gen-cpp") {
        let pattern = matches.value_of("pattern").unwrap_or("gen");
        let cpp = matches.value_of("cpp-extension").unwrap_or("cc");
        let desired_number = matches
            .value_of("generate-exact")
            .map(|s| s.parse::<usize>().unwrap());
        let mut counter = 0usize;
        for include_cxx in parsed_file.get_autocxxes() {
            let generations = include_cxx
                .generate_h_and_cxx()
                .expect("Unable to generate header and C++ code");
            for pair in generations.0 {
                let cppname = format!("{}{}.{}", pattern, counter, cpp);
                write_to_file(&outdir, cppname, &pair.implementation);
                write_to_file(&outdir, pair.header_name, &pair.header);
                counter += 1;
            }
        }
        if let Some(desired_number) = desired_number {
            while counter < desired_number {
                write_cpp_file(
                    &outdir,
                    pattern,
                    cpp,
                    counter,
                    "// Blank C++ file generated by autocxx".as_bytes(),
                );
                counter += 1;
            }
        }
    } else if matches.subcommand_matches("gen-rs").is_some() {
        let mut ts = TokenStream::new();
        parsed_file.to_tokens(&mut ts);
        write_to_file(&outdir, "gen.rs".to_string(), ts.to_string().as_bytes());
    } else {
        panic!("Must specify a subcommand");
    }
}

fn write_cpp_file(outdir: &Path, pattern: &str, cpp: &str, counter: usize, content: &[u8]) {
    let cppname = format!("{}{}.{}", pattern, counter, cpp);
    write_to_file(outdir, cppname, content);
}

fn write_to_file(dir: &Path, filename: String, content: &[u8]) {
    let path = dir.join(filename);
    let mut f = File::create(&path).expect("Unable to create file");
    f.write_all(content).expect("Unable to write file");
}
<commit_msg>Don't change files unnecessarily.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use autocxx_engine::parse_file;
use clap::{crate_authors, crate_version, App, Arg, SubCommand};
use indoc::indoc;
use proc_macro2::TokenStream;
use quote::ToTokens;
use std::io::{Read, Write};
use std::path::PathBuf;
use std::{fs::File, path::Path};

fn main() {
    let matches = App::new("autocxx-gen")
        .version(crate_version!())
        .author(crate_authors!())
        .about("Generates C++ files from Rust files that contain include_cpp! macros")
        .long_about(indoc! {"
                Command line utility to expand the Rust 'autocxx'
                include_cpp macro. Normal usage here is to use the gen-cpp
                subcommand to generate the .cpp and .h side of the bindings,
                such that you can build them and link them to Rust code.
                You can also use this utility
                to expand the Rust code if you wish to avoid a dependency
                on a C++ include path within your Rust build process.
        "})
        .arg(
            Arg::with_name("INPUT")
                .help("Sets the input .rs file to use")
                .required(true)
                .index(1),
        )
        .arg(
            Arg::with_name("outdir")
                .short("o")
                .long("outdir")
                .value_name("PATH")
                .help("output directory path")
                .takes_value(true)
                .required(true),
        )
        .arg(
            Arg::with_name("inc")
                .long("inc")
                .value_name("INCLUDE DIRS")
                .help("include path")
                .takes_value(true),
        )
        .subcommand(
            SubCommand::with_name("gen-cpp")
                .help("Generate C++ .cpp and .h files. Normal mode of operation.")
                .arg(
                    Arg::with_name("pattern")
                        .long("pattern")
                        .value_name("PATTERN")
                        .help(".h and .cpp output pattern")
                        .default_value("gen")
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("cpp-extension")
                        .long("cpp-extension")
                        .value_name("EXTENSION")
                        .default_value("cc")
                        .help("include path")
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("generate-exact")
                        .long("generate-exact")
                        .value_name("NUM")
                        .help("always generate this number of .cc and .h files")
                        .takes_value(true),
                ),
        )
        .subcommand(SubCommand::with_name("gen-rs").help("Generate expanded Rust file."))
        .get_matches();
    let mut parsed_file = parse_file(matches.value_of("INPUT").unwrap())
        .expect("Unable to parse Rust file and interpret autocxx macro");
    let incs = matches.value_of("inc").unwrap_or("");
    // In future, we should provide an option to write a .d file here
    // by passing a callback into the dep_recorder parameter here.
    // https://github.com/google/autocxx/issues/56
    parsed_file
        .resolve_all(incs, None)
        .expect("Unable to resolve macro");
    let outdir: PathBuf = matches.value_of_os("outdir").unwrap().into();
    if let Some(matches) = matches.subcommand_matches("gen-cpp") {
        let pattern = matches.value_of("pattern").unwrap_or("gen");
        let cpp = matches.value_of("cpp-extension").unwrap_or("cc");
        let desired_number = matches
            .value_of("generate-exact")
            .map(|s| s.parse::<usize>().unwrap());
        let mut counter = 0usize;
        for include_cxx in parsed_file.get_autocxxes() {
            let generations = include_cxx
                .generate_h_and_cxx()
                .expect("Unable to generate header and C++ code");
            for pair in generations.0 {
                let cppname = format!("{}{}.{}", pattern, counter, cpp);
                write_to_file(&outdir, cppname, &pair.implementation);
                write_to_file(&outdir, pair.header_name, &pair.header);
                counter += 1;
            }
        }
        if let Some(desired_number) = desired_number {
            while counter < desired_number {
                write_cpp_file(
                    &outdir,
                    pattern,
                    cpp,
                    counter,
                    "// Blank C++ file generated by autocxx".as_bytes(),
                );
                counter += 1;
            }
        }
    } else if matches.subcommand_matches("gen-rs").is_some() {
        let mut ts = TokenStream::new();
        parsed_file.to_tokens(&mut ts);
        write_to_file(&outdir, "gen.rs".to_string(), ts.to_string().as_bytes());
    } else {
        panic!("Must specify a subcommand");
    }
}

fn write_cpp_file(outdir: &Path, pattern: &str, cpp: &str, counter: usize, content: &[u8]) {
    let cppname = format!("{}{}.{}", pattern, counter, cpp);
    write_to_file(outdir, cppname, content);
}

fn write_to_file(dir: &Path, filename: String, content: &[u8]) {
    let path = dir.join(filename);
    {
        let f = File::open(&path);
        if let Ok(mut f) = f {
            let mut existing_content = Vec::new();
            let r = f.read_to_end(&mut existing_content);
            if r.is_ok() && existing_content == content {
                return; // don't change timestamp on existing file unnecessarily
            }
        }
    }
    let mut f = File::create(&path).expect("Unable to create file");
    f.write_all(content).expect("Unable to write file");
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Configuration options for a single run of the servo application. Created
//! from command line arguments.

use geometry::{DevicePixel, ScreenPx};

use azure::azure_hl::{BackendType, CairoBackend, CoreGraphicsBackend};
use azure::azure_hl::{CoreGraphicsAcceleratedBackend, Direct2DBackend, SkiaBackend};
use geom::scale_factor::ScaleFactor;
use getopts;
use std::cmp;
use std::io;
use std::os;
use std::rt;

/// Global flags for Servo, currently set on the command line.
#[deriving(Clone)]
pub struct Opts {
    /// The initial URLs to load.
    pub urls: Vec<String>,

    /// The rendering backend to use (`-r`).
    pub render_backend: BackendType,

    /// How many threads to use for CPU rendering (`-t`).
    ///
    /// FIXME(pcwalton): This is not currently used. All rendering is sequential.
    pub n_render_threads: uint,

    /// True to use CPU painting, false to use GPU painting via Skia-GL (`-c`). Note that
    /// compositing is always done on the GPU.
    pub cpu_painting: bool,

    /// The maximum size of each tile in pixels (`-s`).
    pub tile_size: uint,

    /// The ratio of device pixels per px at the default scale. If unspecified, will use the
    /// platform default setting.
    pub device_pixels_per_px: Option<ScaleFactor<ScreenPx, DevicePixel, f32>>,

    /// `None` to disable the profiler or `Some` with an interval in seconds to enable it and cause
    /// it to produce output on that interval (`-p`).
    pub profiler_period: Option<f64>,

    /// The number of threads to use for layout (`-y`). Defaults to 1, which results in a recursive
    /// sequential algorithm.
    pub layout_threads: uint,

    /// True to exit after the page load (`-x`).
    pub exit_after_load: bool,

    pub output_file: Option<String>,
    pub headless: bool,
    pub hard_fail: bool,

    /// True if we should bubble intrinsic widths sequentially (`-b`). If this is true, then
    /// intrinsic widths are computed as a separate pass instead of during flow construction. You
    /// may wish to turn this flag on in order to benchmark style recalculation against other
    /// browser engines.
    pub bubble_widths_separately: bool,

    /// Use native threads instead of green threads
    pub native_threading: bool
}

fn print_usage(app: &str, opts: &[getopts::OptGroup]) {
    let message = format!("Usage: {} [ options ... ] [URL]\n\twhere options include", app);
    println!("{}", getopts::usage(message.as_slice(), opts));
}

fn args_fail(msg: &str) {
    io::stderr().write_line(msg).unwrap();
    os::set_exit_status(1);
}

pub fn from_cmdline_args(args: &[String]) -> Option<Opts> {
    let app_name = args[0].to_str();
    let args = args.tail();

    let opts = vec![
        getopts::optflag("c", "cpu", "CPU rendering"),
        getopts::optopt("o", "output", "Output file", "output.png"),
        getopts::optopt("r", "rendering", "Rendering backend", "direct2d|core-graphics|core-graphics-accelerated|cairo|skia."),
        getopts::optopt("s", "size", "Size of tiles", "512"),
        getopts::optopt("", "device-pixel-ratio", "Device pixels per px", ""),
        getopts::optflagopt("p", "profile", "Profiler flag and output interval", "10"),
        getopts::optflag("x", "exit", "Exit after load flag"),
        getopts::optopt("t", "threads", "Number of render threads", "[n-cores]"),
        getopts::optopt("y", "layout-threads", "Number of layout threads", "1"),
        getopts::optflag("z", "headless", "Headless mode"),
        getopts::optflag("f", "hard-fail", "Exit on task failure instead of displaying about:failure"),
        getopts::optflag("b", "bubble-widths", "Bubble intrinsic widths separately like other engines"),
        getopts::optflag("n", "native-threading", "Use native threading instead of green threading"),
        getopts::optflag("h", "help", "Print this message")
    ];

    let opt_match = match getopts::getopts(args, opts.as_slice()) {
        Ok(m) => m,
        Err(f) => {
            args_fail(f.to_err_msg().as_slice());
            return None;
        }
    };

    if opt_match.opt_present("h") || opt_match.opt_present("help") {
        print_usage(app_name.as_slice(), opts.as_slice());
        return None;
    };

    let urls = if opt_match.free.is_empty() {
        print_usage(app_name.as_slice(), opts.as_slice());
        args_fail("servo asks that you provide 1 or more URLs");
        return None;
    } else {
        opt_match.free.clone()
    };

    let render_backend = match opt_match.opt_str("r") {
        Some(backend_str) => {
            if "direct2d" == backend_str.as_slice() {
                Direct2DBackend
            } else if "core-graphics" == backend_str.as_slice() {
                CoreGraphicsBackend
            } else if "core-graphics-accelerated" == backend_str.as_slice() {
                CoreGraphicsAcceleratedBackend
            } else if "cairo" == backend_str.as_slice() {
                CairoBackend
            } else if "skia" == backend_str.as_slice() {
                SkiaBackend
            } else {
                fail!("unknown backend type")
            }
        }
        None => SkiaBackend
    };

    let tile_size: uint = match opt_match.opt_str("s") {
        Some(tile_size_str) => from_str(tile_size_str.as_slice()).unwrap(),
        None => 512,
    };

    let device_pixels_per_px = opt_match.opt_str("device-pixel-ratio").map(|dppx_str|
        ScaleFactor(from_str(dppx_str.as_slice()).unwrap())
    );

    let n_render_threads: uint = match opt_match.opt_str("t") {
        Some(n_render_threads_str) => from_str(n_render_threads_str.as_slice()).unwrap(),
        None => {
            // FIXME (rust/14707): This still isn't exposed publicly via std::rt??
            // FIXME (rust/14704): Terrible name for this lint, which here is allowing
            //                     Rust types, not C types
            #[allow(ctypes)]
            extern {
                fn rust_get_num_cpus() -> uint;
            }

            unsafe { rust_get_num_cpus() as uint }
        }
    };

    // if only flag is present, default to 5 second period
    let profiler_period = opt_match.opt_default("p", "5").map(|period| {
        from_str(period.as_slice()).unwrap()
    });

    let cpu_painting = opt_match.opt_present("c");

    let layout_threads: uint = match opt_match.opt_str("y") {
        Some(layout_threads_str) => from_str(layout_threads_str.as_slice()).unwrap(),
        None => cmp::max(rt::default_sched_threads() * 3 / 4, 1),
    };

    let native_threading = opt_match.opt_present("n") || opt_match.opt_present("native-threading");

    Some(Opts {
        urls: urls,
        render_backend: render_backend,
        n_render_threads: n_render_threads,
        cpu_painting: cpu_painting,
        tile_size: tile_size,
        device_pixels_per_px: device_pixels_per_px,
        profiler_period: profiler_period,
        layout_threads: layout_threads,
        exit_after_load: opt_match.opt_present("x"),
        output_file: opt_match.opt_str("o"),
        headless: opt_match.opt_present("z"),
        hard_fail: opt_match.opt_present("f"),
        bubble_widths_separately: opt_match.opt_present("b"),
        native_threading: native_threading
    })
}
<commit_msg>Remove the long-hand handling about 'native-threading' option.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Configuration options for a single run of the servo application. Created
//! from command line arguments.

use geometry::{DevicePixel, ScreenPx};

use azure::azure_hl::{BackendType, CairoBackend, CoreGraphicsBackend};
use azure::azure_hl::{CoreGraphicsAcceleratedBackend, Direct2DBackend, SkiaBackend};
use geom::scale_factor::ScaleFactor;
use getopts;
use std::cmp;
use std::io;
use std::os;
use std::rt;

/// Global flags for Servo, currently set on the command line.
#[deriving(Clone)]
pub struct Opts {
    /// The initial URLs to load.
    pub urls: Vec<String>,

    /// The rendering backend to use (`-r`).
    pub render_backend: BackendType,

    /// How many threads to use for CPU rendering (`-t`).
    ///
    /// FIXME(pcwalton): This is not currently used. All rendering is sequential.
    pub n_render_threads: uint,

    /// True to use CPU painting, false to use GPU painting via Skia-GL (`-c`). Note that
    /// compositing is always done on the GPU.
    pub cpu_painting: bool,

    /// The maximum size of each tile in pixels (`-s`).
    pub tile_size: uint,

    /// The ratio of device pixels per px at the default scale. If unspecified, will use the
    /// platform default setting.
    pub device_pixels_per_px: Option<ScaleFactor<ScreenPx, DevicePixel, f32>>,

    /// `None` to disable the profiler or `Some` with an interval in seconds to enable it and cause
    /// it to produce output on that interval (`-p`).
    pub profiler_period: Option<f64>,

    /// The number of threads to use for layout (`-y`). Defaults to 1, which results in a recursive
    /// sequential algorithm.
    pub layout_threads: uint,

    /// True to exit after the page load (`-x`).
    pub exit_after_load: bool,

    pub output_file: Option<String>,
    pub headless: bool,
    pub hard_fail: bool,

    /// True if we should bubble intrinsic widths sequentially (`-b`). If this is true, then
    /// intrinsic widths are computed as a separate pass instead of during flow construction. You
    /// may wish to turn this flag on in order to benchmark style recalculation against other
    /// browser engines.
    pub bubble_widths_separately: bool,

    /// Use native threads instead of green threads
    pub native_threading: bool
}

fn print_usage(app: &str, opts: &[getopts::OptGroup]) {
    let message = format!("Usage: {} [ options ... ] [URL]\n\twhere options include", app);
    println!("{}", getopts::usage(message.as_slice(), opts));
}

fn args_fail(msg: &str) {
    io::stderr().write_line(msg).unwrap();
    os::set_exit_status(1);
}

pub fn from_cmdline_args(args: &[String]) -> Option<Opts> {
    let app_name = args[0].to_str();
    let args = args.tail();

    let opts = vec![
        getopts::optflag("c", "cpu", "CPU rendering"),
        getopts::optopt("o", "output", "Output file", "output.png"),
        getopts::optopt("r", "rendering", "Rendering backend", "direct2d|core-graphics|core-graphics-accelerated|cairo|skia."),
        getopts::optopt("s", "size", "Size of tiles", "512"),
        getopts::optopt("", "device-pixel-ratio", "Device pixels per px", ""),
        getopts::optflagopt("p", "profile", "Profiler flag and output interval", "10"),
        getopts::optflag("x", "exit", "Exit after load flag"),
        getopts::optopt("t", "threads", "Number of render threads", "[n-cores]"),
        getopts::optopt("y", "layout-threads", "Number of layout threads", "1"),
        getopts::optflag("z", "headless", "Headless mode"),
        getopts::optflag("f", "hard-fail", "Exit on task failure instead of displaying about:failure"),
        getopts::optflag("b", "bubble-widths", "Bubble intrinsic widths separately like other engines"),
        getopts::optflag("n", "native-threading", "Use native threading instead of green threading"),
        getopts::optflag("h", "help", "Print this message")
    ];

    let opt_match = match getopts::getopts(args, opts.as_slice()) {
        Ok(m) => m,
        Err(f) => {
            args_fail(f.to_err_msg().as_slice());
            return None;
        }
    };

    if opt_match.opt_present("h") || opt_match.opt_present("help") {
        print_usage(app_name.as_slice(), opts.as_slice());
        return None;
    };

    let urls = if opt_match.free.is_empty() {
        print_usage(app_name.as_slice(), opts.as_slice());
        args_fail("servo asks that you provide 1 or more URLs");
        return None;
    } else {
        opt_match.free.clone()
    };

    let render_backend = match opt_match.opt_str("r") {
        Some(backend_str) => {
            if "direct2d" == backend_str.as_slice() {
                Direct2DBackend
            } else if "core-graphics" == backend_str.as_slice() {
                CoreGraphicsBackend
            } else if "core-graphics-accelerated" == backend_str.as_slice() {
                CoreGraphicsAcceleratedBackend
            } else if "cairo" == backend_str.as_slice() {
                CairoBackend
            } else if "skia" == backend_str.as_slice() {
                SkiaBackend
            } else {
                fail!("unknown backend type")
            }
        }
        None => SkiaBackend
    };

    let tile_size: uint = match opt_match.opt_str("s") {
        Some(tile_size_str) => from_str(tile_size_str.as_slice()).unwrap(),
        None => 512,
    };

    let device_pixels_per_px = opt_match.opt_str("device-pixel-ratio").map(|dppx_str|
        ScaleFactor(from_str(dppx_str.as_slice()).unwrap())
    );

    let n_render_threads: uint = match opt_match.opt_str("t") {
        Some(n_render_threads_str) => from_str(n_render_threads_str.as_slice()).unwrap(),
        None => {
            // FIXME (rust/14707): This still isn't exposed publicly via std::rt??
            // FIXME (rust/14704): Terrible name for this lint, which here is allowing
            //                     Rust types, not C types
            #[allow(ctypes)]
            extern {
                fn rust_get_num_cpus() -> uint;
            }

            unsafe { rust_get_num_cpus() as uint }
        }
    };

    // if only flag is present, default to 5 second period
    let profiler_period = opt_match.opt_default("p", "5").map(|period| {
        from_str(period.as_slice()).unwrap()
    });

    let cpu_painting = opt_match.opt_present("c");

    let layout_threads: uint = match opt_match.opt_str("y") {
        Some(layout_threads_str) => from_str(layout_threads_str.as_slice()).unwrap(),
        None => cmp::max(rt::default_sched_threads() * 3 / 4, 1),
    };

    let native_threading = opt_match.opt_present("n");

    Some(Opts {
        urls: urls,
        render_backend: render_backend,
        n_render_threads: n_render_threads,
        cpu_painting: cpu_painting,
        tile_size: tile_size,
        device_pixels_per_px: device_pixels_per_px,
        profiler_period: profiler_period,
        layout_threads: layout_threads,
        exit_after_load: opt_match.opt_present("x"),
        output_file: opt_match.opt_str("o"),
        headless: opt_match.opt_present("z"),
        hard_fail: opt_match.opt_present("f"),
        bubble_widths_separately: opt_match.opt_present("b"),
        native_threading: native_threading
    })
}
<|endoftext|>


<commit_before>//
// Created by Eugene Cherkasov on 26.08.2016.
// Copyright (c) 2014-2016 stage team. All rights reserved.
//

//! Point contains coordinates only. Supports basic math operations.
//! For now implemented for 2-dimensional space only.

use std::ops::{Add, Sub};
use structs::Number;

/// A point in 2-dimensional space
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub struct Point2<T: Number> {
    pub x: T,
    pub y: T
}

impl<T> Add for Point2<T> where T: Number, <T as Add>::Output: Number {
    type Output = Point2<<T as Add>::Output>;

    fn add(self, rhs: Point2<T>) -> Point2<<T as Add>::Output> {
        Point2 { x: self.x + rhs.x, y: self.y + rhs.y }
    }
}

impl<T> Sub for Point2<T> where T: Number, <T as Sub>::Output: Number {
    type Output = Point2<<T as Sub>::Output>;

    fn sub(self, rhs: Point2<T>) -> Point2<<T as Sub>::Output> {
        Point2 { x: self.x - rhs.x, y: self.y - rhs.y }
    }
}

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

    const POINT_1: Point2<u32> = Point2{ x: 10, y: 20 };
    const POINT_2: Point2<u32> = Point2{ x: 20, y: 20 };

    #[test]
    fn test_equal() {
        assert_eq!( POINT_1 == POINT_2, false );
    }

    #[test]
    fn test_copy() {
        let p = POINT_1;
        assert_eq!(p, POINT_1);
    }

    #[test]
    fn test_ops() {
        let pAdd = Point2{ x: POINT_1.x + POINT_2.x, y: POINT_1.y + POINT_2.y };
        assert_eq!(p, POINT_1 + POINT_2);
    }
}
<commit_msg>Fix errors.<commit_after>//
// Created by Eugene Cherkasov on 26.08.2016.
// Copyright (c) 2014-2016 stage team. All rights reserved.
//

//! Point contains coordinates only. Supports basic math operations.
//! For now implemented for 2-dimensional space only.

use std::ops::{Add, Sub};
use Number;

/// A point in 2-dimensional space
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub struct Point2<T: Number> {
    pub x: T,
    pub y: T
}

impl<T> Add for Point2<T> where T: Number, <T as Add>::Output: Number {
    type Output = Point2<<T as Add>::Output>;

    fn add(self, rhs: Point2<T>) -> Point2<<T as Add>::Output> {
        Point2 { x: self.x + rhs.x, y: self.y + rhs.y }
    }
}

impl<T> Sub for Point2<T> where T: Number, <T as Sub>::Output: Number {
    type Output = Point2<<T as Sub>::Output>;

    fn sub(self, rhs: Point2<T>) -> Point2<<T as Sub>::Output> {
        Point2 { x: self.x - rhs.x, y: self.y - rhs.y }
    }
}

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

    const POINT_1: Point2<u32> = Point2{ x: 10, y: 20 };
    const POINT_2: Point2<u32> = Point2{ x: 20, y: 20 };

    #[test]
    fn test_equal() {
        assert_eq!( POINT_1 == POINT_2, false );
    }

    #[test]
    fn test_copy() {
        let p = POINT_1;
        assert_eq!(p, POINT_1);
    }

    #[test]
    fn test_ops() {
        let p_add = Point2{ x: POINT_1.x + POINT_2.x, y: POINT_1.y + POINT_2.y };
        assert_eq!(p_add, POINT_1 + POINT_2);
    }
}
<|endoftext|>


<commit_before>extern crate xml;

use std::cmp;
use std::env;
use std::io::Write;
use std::fs::File;
use std::collections::HashSet;

use xml::ParserConfig;
use xml::reader::XmlEvent;

macro_rules! abort {
    ($code:expr) => {::std::process::exit($code)};
    ($code:expr, $($args:tt)+) => {{
        writeln!(&mut ::std::io::stderr(), $($args)+).unwrap();
        ::std::process::exit($code);
    }}
}

fn main() {
    let file_name = env::args().nth(1)
        .unwrap_or_else(|| abort!(1, "XML document is not specified"));
    let file = File::open(file_name)
        .unwrap_or_else(|e| abort!(1, "Cannot open input file: {}", e));
    let reader = ParserConfig::new()
        .whitespace_to_characters(true)
        .ignore_comments(false)
        .create_reader(file);

    let mut processing_instructions = 0;
    let mut elements = 0;
    let mut character_blocks = 0;
    let mut cdata_blocks = 0;
    let mut characters = 0;
    let mut comment_blocks = 0;
    let mut comment_characters = 0;
    let mut namespaces = HashSet::new();
    let mut depth = 0;
    let mut max_depth = 0;

    for e in reader {
        match e {
            Ok(e) => match e {
                XmlEvent::StartDocument { version, encoding, standalone } =>
                    println!(
                        "XML document version {}, encoded in {}, {}standalone",
                        version, encoding, if standalone.unwrap_or(false) { "" } else { "not " }
                    ),
                XmlEvent::EndDocument => println!("Document finished"),
                XmlEvent::ProcessingInstruction { .. } => processing_instructions += 1,
                XmlEvent::Whitespace(_) => {}  // can't happen due to configuration
                XmlEvent::Characters(s) => {
                    character_blocks += 1;
                    characters += s.len();
                }
                XmlEvent::CData(s) => {
                    cdata_blocks += 1;
                    characters += s.len();
                }
                XmlEvent::Comment(s) => {
                    comment_blocks += 1;
                    comment_characters += s.len();
                }
                XmlEvent::StartElement { namespace, .. } => {
                    depth += 1;
                    max_depth = cmp::max(max_depth, depth);
                    elements += 1;
                    namespaces.extend(namespace.0.into_iter().map(|(_, ns_uri)| ns_uri));
                }
                XmlEvent::EndElement { .. } => {
                    depth -= 1;
                }
            },
            Err(e) => abort!(1, "Error parsing XML document: {}", e)
        }
    }

    println!("Elements: {}, maximum depth: {}", elements, max_depth);
    println!("Namespaces: {}", namespaces.len());
    println!("Characters: {}, characters blocks: {}, CDATA blocks: {}",
             characters, character_blocks, cdata_blocks);
    println!("Comment blocks: {}, comment characters: {}", comment_blocks, comment_characters);
    println!("Processing instructions (excluding built-in): {}", processing_instructions);
}
<commit_msg>Improved the analyzer<commit_after>extern crate xml;

use std::cmp;
use std::env;
use std::io::{self, Read, Write, BufReader};
use std::fs::File;
use std::collections::HashSet;

use xml::ParserConfig;
use xml::reader::XmlEvent;

macro_rules! abort {
    ($code:expr) => {::std::process::exit($code)};
    ($code:expr, $($args:tt)+) => {{
        writeln!(&mut ::std::io::stderr(), $($args)+).unwrap();
        ::std::process::exit($code);
    }}
}

fn main() {
    let mut file;
    let mut stdin;
    let source: &mut Read = match env::args().nth(1) {
        Some(file_name) => {
            file = File::open(file_name)
                .unwrap_or_else(|e| abort!(1, "Cannot open input file: {}", e));
            &mut file
        }
        None => {
            stdin = io::stdin();
            &mut stdin
        }
    };

    let reader = ParserConfig::new()
        .whitespace_to_characters(true)
        .ignore_comments(false)
        .create_reader(BufReader::new(source));

    let mut processing_instructions = 0;
    let mut elements = 0;
    let mut character_blocks = 0;
    let mut cdata_blocks = 0;
    let mut characters = 0;
    let mut comment_blocks = 0;
    let mut comment_characters = 0;
    let mut namespaces = HashSet::new();
    let mut depth = 0;
    let mut max_depth = 0;

    for e in reader {
        match e {
            Ok(e) => match e {
                XmlEvent::StartDocument { version, encoding, standalone } =>
                    println!(
                        "XML document version {}, encoded in {}, {}standalone",
                        version, encoding, if standalone.unwrap_or(false) { "" } else { "not " }
                    ),
                XmlEvent::EndDocument => println!("Document finished"),
                XmlEvent::ProcessingInstruction { .. } => processing_instructions += 1,
                XmlEvent::Whitespace(_) => {}  // can't happen due to configuration
                XmlEvent::Characters(s) => {
                    character_blocks += 1;
                    characters += s.len();
                }
                XmlEvent::CData(s) => {
                    cdata_blocks += 1;
                    characters += s.len();
                }
                XmlEvent::Comment(s) => {
                    comment_blocks += 1;
                    comment_characters += s.len();
                }
                XmlEvent::StartElement { namespace, .. } => {
                    depth += 1;
                    max_depth = cmp::max(max_depth, depth);
                    elements += 1;
                    namespaces.extend(namespace.0.into_iter().map(|(_, ns_uri)| ns_uri));
                }
                XmlEvent::EndElement { .. } => {
                    depth -= 1;
                }
            },
            Err(e) => abort!(1, "Error parsing XML document: {}", e)
        }
    }
    namespaces.remove(xml::namespace::NS_EMPTY_URI);
    namespaces.remove(xml::namespace::NS_XMLNS_URI);
    namespaces.remove(xml::namespace::NS_XML_URI);

    println!("Elements: {}, maximum depth: {}", elements, max_depth);
    println!("Namespaces (excluding built-in): {}", namespaces.len());
    println!("Characters: {}, characters blocks: {}, CDATA blocks: {}",
             characters, character_blocks, cdata_blocks);
    println!("Comment blocks: {}, comment characters: {}", comment_blocks, comment_characters);
    println!("Processing instructions (excluding built-in): {}", processing_instructions);
}
<|endoftext|>


<commit_before>use std::net::{SocketAddr, IpAddr, ToSocketAddrs};
use std::io;

use rand;
use mioco::udp::UdpSocket;
use mioco::tcp::{TcpStream};
use trust_dns::op::{Message, MessageType, ResponseCode, Query, OpCode, Edns};

use utils::{Result, Error, CloneExt, MessageExt, WithTimeout, Future};
use utils::with_timeout::TcpStreamExt;
use transport::{DnsTransport, BoundDnsTransport};

pub const QUERY_TIMEOUT: i64 = 5000;
pub const EDNS_VER: u8 = 0;
pub const EDNS_MAX_PAYLOAD: u16 = 1200;

// Idea: Use DNSSEC to check whether a domain is poisoned by GFW

fn query_core<T: DnsTransport>(q: Query, mut transport: BoundDnsTransport<T>, enable_edns: bool) -> Result<Message> {
    let mut msg : Message = Message::new();
    msg.message_type(MessageType::Query);
    msg.id(rand::random());
    msg.op_code(OpCode::Query);
    msg.recursion_desired(true);
    if enable_edns {
        let mut edns = Edns::new();
        edns.set_version(EDNS_VER);
        edns.set_dnssec_ok(false); // TODO
        edns.set_max_payload(EDNS_MAX_PAYLOAD);
        msg.set_edns(edns);
    }
    debug!("Q[{}][{}] {} {:?} {:?}",
           transport, msg.get_id(), q.get_name(), q.get_query_type(), q.get_query_class());
    msg.add_query(q);
    try!(transport.send_msg(&msg));
    loop {
        let (resp, _) = try!(transport.recv_msg());
        if ! resp.is_resp_for(&msg) {
            warn!("Q[{}][{}] Invalid response: {:?}",
                  transport, msg.get_id(), resp);
            continue;
        }
        if resp.get_response_code() == ResponseCode::FormErr && enable_edns {
            // Maybe the server doesn't implement EDNS?
            return query_core(msg.get_queries()[0].clone(), transport, false);
        }
        debug!("A[{}][{}] {:?} {}/{}/{}",
           transport,
           resp.get_id(),
           resp.get_response_code(),
           resp.get_answers().len(),
           resp.get_name_servers().len(),
           resp.get_additional().len(),
        );
        return Ok(resp);
    }
}
fn get_bind_addr(target: &IpAddr) -> SocketAddr {
    (match *target {
        IpAddr::V4(_) => "0.0.0.0:0",
        IpAddr::V6(_) => "[::]:0",
    }).to_socket_addrs().unwrap().next().unwrap()
}
pub fn query(q: Query, addr: IpAddr, enable_edns: bool) -> Result<Message> {
    let target = try!(try!((addr, 53u16).to_socket_addrs()).next().ok_or::<Error>(io::ErrorKind::InvalidInput.into()));
    let mut transport = try!(UdpSocket::bound(&get_bind_addr(&addr))).with_timeout(QUERY_TIMEOUT);
    match query_core(q, transport.bound(Some(&target)), enable_edns) {
        Ok(msg) => {
            if msg.is_truncated() {
                // Try TCP
                let tcp_result = TcpStream::connect_with_timeout(&target, QUERY_TIMEOUT)
                .map_err(|e| e.into())
                .and_then(|stream| stream.set_nodelay(true)
                                         .or_else(|_| Ok(()))
                                         .map(|_| stream))
                .and_then(|stream| query_core(
                    msg.get_queries()[0].clone(),
                    stream.with_timeout(QUERY_TIMEOUT).bound(Some(&target)),
                    enable_edns,
                ));
                Ok(tcp_result.unwrap_or(msg))
            } else {
                Ok(msg)
            }
        },
        Err(e) => Err(e),
    }
}
/* FIXME: Commented out to silence warning. This may be useful again in future.
pub fn query_multiple_build_futures(q: &Query, servers: &[IpAddr]) -> Vec<Future<Result<Message>>> {
    servers.iter()
    .cloned()
    .map(move |server| {
        let qc = q.clone();
        Future::from_fn(move || query(qc, server, true))
    })
    .collect()
}
*/
pub fn query_multiple_handle_futures(futures: &mut Vec<Future<Result<Message>>>) -> Result<Message> {
    if futures.is_empty() {
        return Err(io::ErrorKind::InvalidInput.into());
    }
    loop {
        let result_index = Future::wait_any(futures);
        let result = futures.remove(result_index).consume();
        let mut should_return = futures.is_empty();
        match result {
            Ok(ref msg) => {
                match msg.get_response_code() {
                    ResponseCode::ServFail |
                    ResponseCode::NotImp |
                    ResponseCode::Refused => {
                        // Fall below to wait for remaining servers, if any
                    },
                    _ => { should_return = true; },
                }
            },
            Err(Error::Io(ref err)) if err.kind() == io::ErrorKind::TimedOut => {
                debug!("Timed out");
            },
            Err(ref err) => {
                debug!("Error {:?}", err);
            },
        };
        if should_return {
            return result;
        }
    }
}
/* FIXME: Commented out to silence warning. This may be useful again in future.
pub fn query_multiple(q: &Query, servers: &[IpAddr]) -> Result<Message> {
    let mut futures = query_multiple_build_futures(q, servers);
    query_multiple_handle_futures(&mut futures)
}
*/
<commit_msg>Refactor and add a test<commit_after>use std::net::{SocketAddr, IpAddr};
use std::io;

use rand;
use mioco::udp::UdpSocket;
use mioco::tcp::{TcpStream};
use trust_dns::op::{Message, MessageType, ResponseCode, Query, OpCode, Edns};

use utils::{Result, Error, CloneExt, MessageExt, WithTimeout, Future};
use utils::with_timeout::TcpStreamExt;
use transport::{DnsTransport, BoundDnsTransport};

pub const QUERY_TIMEOUT: i64 = 5000;
pub const EDNS_VER: u8 = 0;
pub const EDNS_MAX_PAYLOAD: u16 = 1200;

// Idea: Use DNSSEC to check whether a domain is poisoned by GFW

fn query_core<T: DnsTransport>(q: Query, mut transport: BoundDnsTransport<T>, enable_edns: bool) -> Result<Message> {
    let mut msg : Message = Message::new();
    msg.message_type(MessageType::Query);
    msg.id(rand::random());
    msg.op_code(OpCode::Query);
    msg.recursion_desired(true);
    if enable_edns {
        let mut edns = Edns::new();
        edns.set_version(EDNS_VER);
        edns.set_dnssec_ok(false); // TODO
        edns.set_max_payload(EDNS_MAX_PAYLOAD);
        msg.set_edns(edns);
    }
    debug!("Q[{}][{}] {} {:?} {:?}",
           transport, msg.get_id(), q.get_name(), q.get_query_type(), q.get_query_class());
    msg.add_query(q);
    try!(transport.send_msg(&msg));
    loop {
        let (resp, _) = try!(transport.recv_msg());
        if ! resp.is_resp_for(&msg) {
            warn!("Q[{}][{}] Invalid response: {:?}",
                  transport, msg.get_id(), resp);
            continue;
        }
        if resp.get_response_code() == ResponseCode::FormErr && enable_edns {
            // Maybe the server doesn't implement EDNS?
            return query_core(msg.get_queries()[0].clone(), transport, false);
        }
        debug!("A[{}][{}] {:?} {}/{}/{}",
           transport,
           resp.get_id(),
           resp.get_response_code(),
           resp.get_answers().len(),
           resp.get_name_servers().len(),
           resp.get_additional().len(),
        );
        return Ok(resp);
    }
}
fn get_bind_addr(target: &IpAddr) -> SocketAddr {
    SocketAddr::new(match *target {
        IpAddr::V4(_) => "0.0.0.0",
        IpAddr::V6(_) => "[::]",
    }.parse().unwrap(), 0)
}
pub fn query(q: Query, addr: IpAddr, enable_edns: bool) -> Result<Message> {
    let target = SocketAddr::new(addr, 53);
    let mut transport = try!(UdpSocket::bound(&get_bind_addr(&addr))).with_timeout(QUERY_TIMEOUT);
    match query_core(q, transport.bound(Some(&target)), enable_edns) {
        Ok(msg) => {
            if msg.is_truncated() {
                // Try TCP
                let tcp_result = TcpStream::connect_with_timeout(&target, QUERY_TIMEOUT)
                .map_err(|e| e.into())
                .and_then(|stream| stream.set_nodelay(true)
                                         .or_else(|_| Ok(()))
                                         .map(|_| stream))
                .and_then(|stream| query_core(
                    msg.get_queries()[0].clone(),
                    stream.with_timeout(QUERY_TIMEOUT).bound(Some(&target)),
                    enable_edns,
                ));
                Ok(tcp_result.unwrap_or(msg))
            } else {
                Ok(msg)
            }
        },
        Err(e) => Err(e),
    }
}
/* FIXME: Commented out to silence warning. This may be useful again in future.
pub fn query_multiple_build_futures(q: &Query, servers: &[IpAddr]) -> Vec<Future<Result<Message>>> {
    servers.iter()
    .cloned()
    .map(move |server| {
        let qc = q.clone();
        Future::from_fn(move || query(qc, server, true))
    })
    .collect()
}
*/
pub fn query_multiple_handle_futures(futures: &mut Vec<Future<Result<Message>>>) -> Result<Message> {
    if futures.is_empty() {
        return Err(io::ErrorKind::InvalidInput.into());
    }
    loop {
        let result_index = Future::wait_any(futures);
        let result = futures.remove(result_index).consume();
        let mut should_return = futures.is_empty();
        match result {
            Ok(ref msg) => {
                match msg.get_response_code() {
                    ResponseCode::ServFail |
                    ResponseCode::NotImp |
                    ResponseCode::Refused => {
                        // Fall below to wait for remaining servers, if any
                    },
                    _ => { should_return = true; },
                }
            },
            Err(Error::Io(ref err)) if err.kind() == io::ErrorKind::TimedOut => {
                debug!("Timed out");
            },
            Err(ref err) => {
                debug!("Error {:?}", err);
            },
        };
        if should_return {
            return result;
        }
    }
}
/* FIXME: Commented out to silence warning. This may be useful again in future.
pub fn query_multiple(q: &Query, servers: &[IpAddr]) -> Result<Message> {
    let mut futures = query_multiple_build_futures(q, servers);
    query_multiple_handle_futures(&mut futures)
}
*/

#[cfg(test)]
mod tests {
    use trust_dns::op::*;
    use trust_dns::rr::*;

    use super::*;
    use ::mioco_config_start;

    #[test]
    fn simple_query() {
        mioco_config_start(|| {
            let mut q = Query::new();
            q.name(Name::parse("www.google.com", Some(&Name::root())).unwrap());
            let result = query(q, "8.8.8.8".parse().unwrap(), true).unwrap();
            assert!(result.get_answers().len() > 0);
        }).unwrap();
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use chrono::{ Date, Duration, Local };
use regex::Regex;

use posting::ClearedStatus;
use quantity::Quantity;

#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Query {
    Any,
    None,
    Not(Rc<Query>),
    Or(Vec<Query>),
    And(Vec<Query>),
    Code(Regex),
    Desc(Regex),
    Acct(Regex),
    Date(Duration),
    Date2(Duration),
    Status(ClearedStatus),
    Real(bool),
    Amount(Quantity),
    Symbol(Regex),
    Empty(bool),
    Depth(usize),
    Tag(Regex, Option<Regex>)
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub enum QueryOption {
    InAccountOnly(String),
    InAccount(String)
}

pub fn parse_query(day: Date<Local>, query: String) -> (Query, Vec<QueryOption>) {
    (Query::None, Vec::new())
}

pub fn in_account(query_opts: &Vec<QueryOption>) -> Option<(String, bool)> {
    for opt in query_opts {
        match opt {
            &QueryOption::InAccountOnly(ref a) => return Some((a.clone(), false)),
            &QueryOption::InAccount(ref a) => return Some((a.clone(), true))
        }
    }

    None
}

pub fn account_name_level(account_name: String) -> usize {
    return 0;
}

pub fn same<T: Eq>(vec: &Vec<T>) -> bool {
    vec.iter().all(|x| vec.first().unwrap() == x)
}

impl Query {
    pub fn matches_account(&self, account_name: String) -> bool {
        match *self {
            Query::None => false,
            Query::Not(ref x) => Query::matches_account(x.as_ref(), account_name),
            Query::Or(ref xs) => xs.iter().any(|x|  Query::matches_account(x, account_name.clone())),
            Query::And(ref xs) => xs.iter().all(|x| Query::matches_account(x, account_name.clone())),
            Query::Depth(d) => account_name_level(account_name) <= d,
            Query::Tag(_, _) => false,
            _ => true,
        }
    }

    fn simplify_helper_and(xs: &Vec<Query>) -> Query {
        match xs.as_slice() {
            [] => Query::Any,
            [ref q] => Query::simplify_helper(q),
            q => {
                if same(xs) {
                    xs.first().unwrap().simplify()
                } else if q.iter().any(|x| *x == Query::None) {
                    Query::None
                } else if q.iter().all(|x| true) {
                    Query::None
                } else {
                    Query::None
                }
            }
        }
    }

    fn simplify_helper_or(xs: &Vec<Query>) -> Query {
        match xs.as_slice() {
            [] => Query::Any,
            [ref q] => Query::simplify_helper(q),
            q => {
                if same(xs) {
                    xs.first().unwrap().simplify()
                } else if q.iter().any(|x| *x == Query::Any) {
                    Query::None
                } else {
                    Query::Or(q.iter().filter(|&x| *x != Query::None).map(|x| x.simplify()).collect())
                }
            }
        }
    }

    fn simplify_helper(query: &Query) -> Query {
        match query {
            &Query::And(ref xs) => Query::simplify_helper_and(xs),
            &Query::Or(ref xs) => Query::simplify_helper_or(xs),
            q => q.clone()
        }
    }

    /// Simplify the query as much as possible
    pub fn simplify(&self) -> Query {
        let q = Query::simplify_helper(self);
        if *self == q {
            self.clone()
        } else {
            q.simplify()
        }
    }

    pub fn filter<F>(&self, pred: F) -> Query where F : Fn(&Query) -> bool {
        match self {
            &Query::And(ref qs) => Query::And(qs.iter().filter(|&x| pred(x)).map(|x| x.clone()).collect()),
            &Query::Or(ref qs) => Query::Or(qs.iter().filter(|&x| pred(x)).map(|x| x.clone()).collect()),
            _ => if pred(self) { self.clone() } else { Query::Any }
        }.simplify()
    }
}

#[test]
fn simplify_test() {
    let q = Query::And(vec!(Query::Or(vec!(Query::Or(vec!(Query::Desc(Regex::new("b b").unwrap())))))));
    let sq = q.simplify();

    assert!(sq == Query::Desc(Regex::new("b b").unwrap()))
}
<commit_msg>adds depth computation to query<commit_after>use std::rc::Rc;
use chrono::{ Date, Duration, Local };
use regex::Regex;

use posting::ClearedStatus;
use quantity::Quantity;

#[derive(Clone, PartialEq, Eq, Debug)]
pub enum OrdPlus {
    Lt,
    LtEq,
    Gt,
    GtEq,
    Eq,
    AbsLt,
    AbsLtEq,
    AbsGt,
    AbsGtEq,
    AbsEq
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Query {
    Any,
    None,
    Not(Rc<Query>),
    Or(Vec<Query>),
    And(Vec<Query>),
    Code(Regex),
    Desc(Regex),
    Acct(Regex),
    Date(Duration),
    Date2(Duration),
    Status(ClearedStatus),
    Real(bool),
    Amount(OrdPlus, Quantity),
    Symbol(Regex),
    Empty(bool),
    Depth(usize),
    Tag(Regex, Option<Regex>)
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub enum QueryOption {
    InAccountOnly(String),
    InAccount(String)
}

pub fn parse_query(day: Date<Local>, query: String) -> (Query, Vec<QueryOption>) {
    (Query::None, Vec::new())
}

pub fn in_account(query_opts: &Vec<QueryOption>) -> Option<(String, bool)> {
    for opt in query_opts {
        match opt {
            &QueryOption::InAccountOnly(ref a) => return Some((a.clone(), false)),
            &QueryOption::InAccount(ref a) => return Some((a.clone(), true))
        }
    }

    None
}

pub fn account_name_level(account_name: String) -> usize {
    return 0;
}

pub fn same<T: Eq>(vec: &Vec<T>) -> bool {
    vec.iter().all(|x| vec.first().unwrap() == x)
}

impl Query {
    pub fn matches_account(&self, account_name: String) -> bool {
        match *self {
            Query::None => false,
            Query::Not(ref x) => Query::matches_account(x.as_ref(), account_name),
            Query::Or(ref xs) => xs.iter().any(|x|  Query::matches_account(x, account_name.clone())),
            Query::And(ref xs) => xs.iter().all(|x| Query::matches_account(x, account_name.clone())),
            Query::Depth(d) => account_name_level(account_name) <= d,
            Query::Tag(_, _) => false,
            _ => true,
        }
    }

    fn simplify_helper_and(xs: &Vec<Query>) -> Query {
        match xs.as_slice() {
            [] => Query::Any,
            [ref q] => Query::simplify_helper(q),
            q => {
                if same(xs) {
                    xs.first().unwrap().simplify()
                } else if q.iter().any(|x| *x == Query::None) {
                    Query::None
                } else if q.iter().all(|x| true) {
                    Query::None
                } else {
                    Query::None
                }
            }
        }
    }

    fn simplify_helper_or(xs: &Vec<Query>) -> Query {
        match xs.as_slice() {
            [] => Query::Any,
            [ref q] => Query::simplify_helper(q),
            q => {
                if same(xs) {
                    xs.first().unwrap().simplify()
                } else if q.iter().any(|x| *x == Query::Any) {
                    Query::None
                } else {
                    Query::Or(q.iter().filter(|&x| *x != Query::None).map(|x| x.simplify()).collect())
                }
            }
        }
    }

    fn simplify_helper(query: &Query) -> Query {
        match query {
            &Query::And(ref xs) => Query::simplify_helper_and(xs),
            &Query::Or(ref xs) => Query::simplify_helper_or(xs),
            q => q.clone()
        }
    }

    /// Simplify the query as much as possible
    pub fn simplify(&self) -> Query {
        let q = Query::simplify_helper(self);
        if *self == q {
            self.clone()
        } else {
            q.simplify()
        }
    }

    pub fn filter<F>(&self, pred: F) -> Query where F : Fn(&Query) -> bool {
        match self {
            &Query::And(ref qs) => Query::And(qs.iter().filter(|&x| pred(x)).map(|x| x.clone()).collect()),
            &Query::Or(ref qs) => Query::Or(qs.iter().filter(|&x| pred(x)).map(|x| x.clone()).collect()),
            _ => if pred(self) { self.clone() } else { Query::Any }
        }.simplify()
    }

    pub fn is_null(&self) -> bool {
        match self {
            &Query::Any => true,
            &Query::And(ref q) => q.is_empty(),
            &Query::Not(ref r) => match r.as_ref() {
                &Query::Or(ref q) => q.is_empty(),
                _ => false
            },
            _ => false
        }
    }

    pub fn is_depth(&self) -> bool {
        match self {
            &Query::Depth(_) => true,
            _ => false
        }
    }

    pub fn depth(&self) -> usize {
        fn depth_helper(query: &Query) -> Vec<usize> {

            match query {
                &Query::Depth(d) => vec!(d),
                &Query::Or(ref q) => q.iter().flat_map(|x| depth_helper(x)).collect(),
                &Query::And(ref q) => q.iter().flat_map(|x| depth_helper(x)).collect(),
                _ => Vec::new()
            }
        }

        let q = depth_helper(self);
        let r = q.iter().min();

        match r {
            None => 99999,
            Some(x) => *x
        }
    }
}

#[test]
fn simplify_test() {
    let q = Query::And(vec!(Query::Or(vec!(Query::Or(vec!(Query::Desc(Regex::new("b b").unwrap())))))));
    let sq = q.simplify();

    assert!(sq == Query::Desc(Regex::new("b b").unwrap()))
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate indolentjson;
extern crate test;

use indolentjson::strings::*;
use test::Bencher;

#[bench]
fn noop_escape(b: &mut Bencher) {
    b.iter(|| {
        escape_bytes(b"test")
    });
}

#[bench]
fn escape_controls(b: &mut Bencher) {
    b.iter(|| {
        escape_bytes(b"\t\n\r\\")
    });
}

#[bench]
fn noop_unescape(b: &mut Bencher) {
    b.iter(|| {
        unescape_bytes(b"test")
    });
}

#[bench]
fn unescape_controls(b: &mut Bencher) {
    b.iter(|| {
        unescape_bytes(br#"\t\n\r\\"#)
    });
}
<commit_msg>Add a couple more benchmarks, add bytes count so that we get more meaningless numbers<commit_after>#![feature(test)]

extern crate indolentjson;
extern crate test;

use indolentjson::strings::*;
use test::{black_box, Bencher};

#[bench]
fn noop_escape(b: &mut Bencher) {
    let test_string = black_box(b"test");

    b.bytes = test_string.len() as u64;
    b.iter(|| { escape_bytes(test_string) });
}

#[bench]
fn escape_controls(b: &mut Bencher) {
    let test_string = black_box(b"\t\n\r\\\"");

    b.bytes = test_string.len() as u64;
    b.iter(|| { escape_bytes(test_string) });
}

#[bench]
fn escape_mixed(b: &mut Bencher) {
    let test_string = black_box(
        b"This\nIsA\tMixture\x00OfStrings\x0cThat\"Need\\Escaping"
    );

    b.bytes = test_string.len() as u64;
    b.iter(|| { escape_bytes(test_string) });
}

#[bench]
fn noop_unescape(b: &mut Bencher) {
    let test_string = black_box(b"test");

    b.bytes = test_string.len() as u64;
    b.iter(|| { unescape_bytes(test_string) });
}

#[bench]
fn unescape_controls(b: &mut Bencher) {
    let test_string = black_box(br#"\t\n\r\\\""#);

    b.bytes = test_string.len() as u64;
    b.iter(|| { unescape_bytes(test_string) });
}

#[bench]
fn unescape_mixed(b: &mut Bencher) {
    let test_string = black_box(
        br#"This\nIsA\tMixture\u0000OfStrings\fThat\"Need\\Escaping"#
    );

    b.bytes = test_string.len() as u64;
    b.iter(|| { unescape_bytes(test_string) });
}
<|endoftext|>


<commit_before>use std::fmt;
use std::ptr;

fn optional<'a, T>(p: *const T) -> Option<&'a T> {
    match p.is_null() {
        true => None,
        false => unsafe {
            Some(&*p)
        },
    }
}

pub struct Room {
    pub name: String,
    pub description: String,
    north: *mut Room,
    south: *mut Room,
    east: *mut Room,
    west: *mut Room,
}

impl Room {
    pub fn new(name: &str, description: &str) -> Room {
        Room {
            name: name.to_string(),
            description: description.to_string(),
            north: ptr::null_mut(),
            south: ptr::null_mut(),
            east: ptr::null_mut(),
            west: ptr::null_mut(),
        }
    }

    pub fn north(&self) -> Option<&Room> {
        optional(self.north)
    }

    pub fn south(&self) -> Option<&Room> {
        optional(self.south)
    }

    pub fn east(&self) -> Option<&Room> {
        optional(self.east)
    }

    pub fn west(&self) -> Option<&Room> {
        optional(self.west)
    }

    pub fn doors_description(&self) -> String {
        let mut doors: Vec<&str> = Vec::new();
        if ! self.north.is_null() { doors.push("north"); }
        if ! self.south.is_null() { doors.push("south"); }
        if ! self.east.is_null() { doors.push("east"); }
        if ! self.west.is_null() { doors.push("west"); }

        match doors.len() {
            1 => format!("There is a door to the {}.", doors[0]),
            2 => format!("There are doors to the {} and {}.", doors[0], doors[1]),
            3 => format!("There are doors to the {}, {} and {}.",
                         doors[0], doors[1], doors[2]),
            4 => format!("There are doors in all directions."),
            _ => panic!("Found {} doors in {}!", doors.len(), self.name),
        }
    }

    pub fn print_description_on_entrance(&self) {
        println!("You find yourself in {}.", self.description);
        println!("{}", self.doors_description());
    }

    unsafe fn door_north_leads_to(&mut self, room: *mut Room) {
        self.north = room;
        (*room).south = self;
    }

    unsafe fn door_south_leads_to(&mut self, room: *mut Room) {
        self.south = room;
        (*room).north = self;
    }

    unsafe fn door_east_leads_to(&mut self, room: *mut Room) {
        self.east = room;
        (*room).west = self;
    }

    unsafe fn door_west_leads_to(&mut self, room: *mut Room) {
        self.west = room;
        (*room).east = self;
    }
}

impl fmt::Display for Room {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.name)
    }
}

pub struct Rooms {
    pub vec: Vec<Box<Room>>,
}

impl Rooms {
    pub fn new() -> Box<Rooms> {
        let mut rooms = Rooms {
            vec: Vec::new(),
        };

        unsafe {
            let timmys_bedroom = rooms.add_room("Timmy's bedroom", "a young boy's bedroom");
            let upstairs_hallway = rooms.add_room("upstairs hallway", "a hallway");
            (*timmys_bedroom).door_north_leads_to(upstairs_hallway);

            let sallys_bedroom = rooms.add_room("Sally's bedroom",
                                                "a teenage girl's bedroom");
            (*sallys_bedroom).door_west_leads_to(upstairs_hallway);

            let kids_bathroom = rooms.add_room("kid's bathroom",
                                               "a messy bathroom with towels on the floor");
            (*kids_bathroom).door_west_leads_to(timmys_bedroom);
            (*kids_bathroom).door_north_leads_to(sallys_bedroom);

            let master_bedroom = rooms.add_room("master bedroom",
                                                "a bedroom with a king sized bed");
            (*master_bedroom).door_south_leads_to(upstairs_hallway);

            let parents_bathroom = rooms.add_room("parent's bathroom",
                                                  "a bathroom with a shower");
            (*parents_bathroom).door_east_leads_to(master_bedroom);

            let stairway = rooms.add_room("stairway", "a stairway");
            (*stairway).door_east_leads_to(upstairs_hallway);

            let downstairs_hallway = rooms.add_room("downstairs hallway", "a hallway");
            (*downstairs_hallway).door_south_leads_to(stairway);

            let livingroom = rooms.add_room("livingroom",
                                            "a large room with a comfy sofa and a big TV");
            (*livingroom).door_south_leads_to(downstairs_hallway);

            let kitchen = rooms.add_room("kitchen",
                                         "a large room with a tile floor that smells like food");
            (*kitchen).door_west_leads_to(downstairs_hallway);
        }
        Box::new(rooms)
    }

    fn add_room(&mut self, name: &str, description: &str) -> *mut Room {
        self.vec.push(Box::new(Room::new(name, description)));
        &mut **self.vec.last_mut().unwrap()
    }

    pub fn first_room(&self) -> &Room {
        self.vec.first().expect("first room")
    }
}

<commit_msg>Renamed optional() to as_option().<commit_after>use std::fmt;
use std::ptr;

fn as_option<'a, T>(p: *const T) -> Option<&'a T> {
    match p.is_null() {
        true => None,
        false => unsafe {
            Some(&*p)
        },
    }
}

pub struct Room {
    pub name: String,
    pub description: String,
    north: *mut Room,
    south: *mut Room,
    east: *mut Room,
    west: *mut Room,
}

impl Room {
    pub fn new(name: &str, description: &str) -> Room {
        Room {
            name: name.to_string(),
            description: description.to_string(),
            north: ptr::null_mut(),
            south: ptr::null_mut(),
            east: ptr::null_mut(),
            west: ptr::null_mut(),
        }
    }

    pub fn north(&self) -> Option<&Room> {
        as_option(self.north)
    }

    pub fn south(&self) -> Option<&Room> {
        as_option(self.south)
    }

    pub fn east(&self) -> Option<&Room> {
        as_option(self.east)
    }

    pub fn west(&self) -> Option<&Room> {
        as_option(self.west)
    }

    pub fn doors_description(&self) -> String {
        let mut doors: Vec<&str> = Vec::new();
        if ! self.north.is_null() { doors.push("north"); }
        if ! self.south.is_null() { doors.push("south"); }
        if ! self.east.is_null() { doors.push("east"); }
        if ! self.west.is_null() { doors.push("west"); }

        match doors.len() {
            1 => format!("There is a door to the {}.", doors[0]),
            2 => format!("There are doors to the {} and {}.", doors[0], doors[1]),
            3 => format!("There are doors to the {}, {} and {}.",
                         doors[0], doors[1], doors[2]),
            4 => format!("There are doors in all directions."),
            _ => panic!("Found {} doors in {}!", doors.len(), self.name),
        }
    }

    pub fn print_description_on_entrance(&self) {
        println!("You find yourself in {}.", self.description);
        println!("{}", self.doors_description());
    }

    unsafe fn door_north_leads_to(&mut self, room: *mut Room) {
        self.north = room;
        (*room).south = self;
    }

    unsafe fn door_south_leads_to(&mut self, room: *mut Room) {
        self.south = room;
        (*room).north = self;
    }

    unsafe fn door_east_leads_to(&mut self, room: *mut Room) {
        self.east = room;
        (*room).west = self;
    }

    unsafe fn door_west_leads_to(&mut self, room: *mut Room) {
        self.west = room;
        (*room).east = self;
    }
}

impl fmt::Display for Room {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.name)
    }
}

pub struct Rooms {
    pub vec: Vec<Box<Room>>,
}

impl Rooms {
    pub fn new() -> Box<Rooms> {
        let mut rooms = Rooms {
            vec: Vec::new(),
        };

        unsafe {
            let timmys_bedroom = rooms.add_room("Timmy's bedroom", "a young boy's bedroom");
            let upstairs_hallway = rooms.add_room("upstairs hallway", "a hallway");
            (*timmys_bedroom).door_north_leads_to(upstairs_hallway);

            let sallys_bedroom = rooms.add_room("Sally's bedroom",
                                                "a teenage girl's bedroom");
            (*sallys_bedroom).door_west_leads_to(upstairs_hallway);

            let kids_bathroom = rooms.add_room("kid's bathroom",
                                               "a messy bathroom with towels on the floor");
            (*kids_bathroom).door_west_leads_to(timmys_bedroom);
            (*kids_bathroom).door_north_leads_to(sallys_bedroom);

            let master_bedroom = rooms.add_room("master bedroom",
                                                "a bedroom with a king sized bed");
            (*master_bedroom).door_south_leads_to(upstairs_hallway);

            let parents_bathroom = rooms.add_room("parent's bathroom",
                                                  "a bathroom with a shower");
            (*parents_bathroom).door_east_leads_to(master_bedroom);

            let stairway = rooms.add_room("stairway", "a stairway");
            (*stairway).door_east_leads_to(upstairs_hallway);

            let downstairs_hallway = rooms.add_room("downstairs hallway", "a hallway");
            (*downstairs_hallway).door_south_leads_to(stairway);

            let livingroom = rooms.add_room("livingroom",
                                            "a large room with a comfy sofa and a big TV");
            (*livingroom).door_south_leads_to(downstairs_hallway);

            let kitchen = rooms.add_room("kitchen",
                                         "a large room with a tile floor that smells like food");
            (*kitchen).door_west_leads_to(downstairs_hallway);
        }
        Box::new(rooms)
    }

    fn add_room(&mut self, name: &str, description: &str) -> *mut Room {
        self.vec.push(Box::new(Room::new(name, description)));
        &mut **self.vec.last_mut().unwrap()
    }

    pub fn first_room(&self) -> &Room {
        self.vec.first().expect("first room")
    }
}

<|endoftext|>