<commit_before>#![feature(async_closure)]
#![feature(box_patterns)]
#![feature(label_break_value)]
#![feature(never_type)]
#![feature(try_trait_v2)]
#![allow(clippy::module_inception)]

mod builtin_functions;
mod compiler;
mod database;
mod fuzzer;
mod language_server;
mod module;
mod vm;

use crate::{
    compiler::{
        ast_to_hir::AstToHir,
        cst_to_ast::CstToAst,
        error::CompilerError,
        hir::{self, CollectErrors},
        hir_to_lir::HirToLir,
        rcst_to_cst::RcstToCst,
        string_to_rcst::StringToRcst,
    },
    database::Database,
    language_server::utils::LspPositionConversion,
    module::{Module, ModuleKind},
    vm::{use_provider::DbUseProvider, Closure, TearDownResult, Vm},
};
use compiler::lir::Lir;
use fern::colors::{Color, ColoredLevelConfig};
use itertools::Itertools;
use language_server::CandyLanguageServer;
use log::{self, LevelFilter};
use notify::{watcher, RecursiveMode, Watcher};
use std::{
    env::current_dir,
    fs,
    path::PathBuf,
    sync::{mpsc::channel, Arc},
    time::Duration,
};
use structopt::StructOpt;
use tower_lsp::{LspService, Server};

#[derive(StructOpt, Debug)]
#[structopt(name = "candy", about = "The 🍭 Candy CLI.")]
enum CandyOptions {
    Build(CandyBuildOptions),
    Run(CandyRunOptions),
    Fuzz(CandyFuzzOptions),
    Lsp,
}

#[derive(StructOpt, Debug)]
struct CandyBuildOptions {
    #[structopt(long)]
    debug: bool,

    #[structopt(long)]
    watch: bool,

    #[structopt(parse(from_os_str))]
    file: PathBuf,
}

#[derive(StructOpt, Debug)]
struct CandyRunOptions {
    #[structopt(long)]
    debug: bool,

    #[structopt(parse(from_os_str))]
    file: PathBuf,
}

#[derive(StructOpt, Debug)]
struct CandyFuzzOptions {
    #[structopt(parse(from_os_str))]
    file: PathBuf,
}

#[tokio::main]
async fn main() {
    init_logger();
    match CandyOptions::from_args() {
        CandyOptions::Build(options) => build(options),
        CandyOptions::Run(options) => run(options),
        CandyOptions::Fuzz(options) => fuzz(options).await,
        CandyOptions::Lsp => lsp().await,
    }
}

fn build(options: CandyBuildOptions) {
    let module = Module::from_package_root_and_file(
        current_dir().unwrap(),
        options.file.clone(),
        ModuleKind::Code,
    );
    raw_build(module.clone(), options.debug);

    if options.watch {
        let (tx, rx) = channel();
        let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
        watcher
            .watch(&options.file, RecursiveMode::Recursive)
            .unwrap();
        loop {
            match rx.recv() {
                Ok(_) => {
                    raw_build(module.clone(), options.debug);
                }
                Err(e) => log::error!("watch error: {e:#?}"),
            }
        }
    }
}
fn raw_build(module: Module, debug: bool) -> Option<Arc<Lir>> {
    log::info!("Building `{module}`.");

    let db = Database::default();

    log::debug!("Parsing string to RCST…");
    let rcst = db
        .rcst(module.clone())
        .unwrap_or_else(|err| panic!("Error parsing file `{}`: {:?}", module, err));
    if debug {
        let rcst_file = module.associated_debug_file("rcst");
        fs::write(rcst_file, format!("{:#?}\n", rcst)).unwrap();
    }

    log::debug!("Turning RCST to CST…");
    let cst = db.cst(module.clone()).unwrap();
    if debug {
        let cst_file = module.associated_debug_file("cst");
        fs::write(cst_file, format!("{:#?}\n", cst)).unwrap();
    }

    log::debug!("Abstracting CST to AST…");
    let (asts, ast_cst_id_map) = db.ast(module.clone()).unwrap();
    if debug {
        let ast_file = module.associated_debug_file("ast");
        fs::write(
            ast_file,
            format!("{}\n", asts.iter().map(|ast| format!("{}", ast)).join("\n")),
        )
        .unwrap();

        let ast_to_cst_ids_file = module.associated_debug_file("ast_to_cst_ids");
        fs::write(
            ast_to_cst_ids_file,
            ast_cst_id_map
                .keys()
                .into_iter()
                .sorted_by_key(|it| it.local)
                .map(|key| format!("{key} -> {}\n", ast_cst_id_map[key].0))
                .join(""),
        )
        .unwrap();
    }

    log::debug!("Turning AST to HIR…");
    let (hir, hir_ast_id_map) = db.hir(module.clone()).unwrap();
    if debug {
        let hir_file = module.associated_debug_file("hir");
        fs::write(hir_file, format!("{}", hir)).unwrap();

        let hir_ast_id_file = module.associated_debug_file("hir_to_ast_ids");
        fs::write(
            hir_ast_id_file,
            hir_ast_id_map
                .keys()
                .into_iter()
                .map(|key| format!("{key} -> {}\n", hir_ast_id_map[key]))
                .join(""),
        )
        .unwrap();
    }

    log::debug!("Lowering HIR to LIR…");
    let lir = db.lir(module.clone()).unwrap();
    if debug {
        let lir_file = module.associated_debug_file("lir");
        fs::write(lir_file, format!("{lir}")).unwrap();
    }

    let mut errors = vec![];
    hir.collect_errors(&mut errors);
    for CompilerError { span, payload, .. } in errors {
        let (start_line, start_col) = db.offset_to_lsp(module.clone(), span.start);
        let (end_line, end_col) = db.offset_to_lsp(module.clone(), span.end);
        log::warn!("{start_line}:{start_col} – {end_line}:{end_col}: {payload:?}");
    }

    Some(lir)
}

fn run(options: CandyRunOptions) {
    let module = Module::from_package_root_and_file(
        current_dir().unwrap(),
        options.file.clone(),
        ModuleKind::Code,
    );
    let db = Database::default();

    if raw_build(module.clone(), false).is_none() {
        log::info!("Build failed.");
        return;
    };
    let module_closure = Closure::of_module(&db, module.clone()).unwrap();

    let path_string = options.file.to_string_lossy();
    log::info!("Running `{path_string}`.");

    let use_provider = DbUseProvider { db: &db };
    let vm = Vm::new_for_running_module_closure(&use_provider, module_closure);
    let TearDownResult { tracer, .. } = vm.run_synchronously_until_completion(&db);

    if options.debug {
        let trace = tracer.dump_call_tree();
        let trace_file = module.associated_debug_file("trace");
        fs::write(trace_file.clone(), trace).unwrap();
        log::info!(
            "Trace has been written to `{}`.",
            trace_file.as_path().display()
        );
    }
}

async fn fuzz(options: CandyFuzzOptions) {
    let module = Module::from_package_root_and_file(
        current_dir().unwrap(),
        options.file.clone(),
        ModuleKind::Code,
    );
    log::debug!("Building `{}`.\n", module);

    if raw_build(module.clone(), false).is_none() {
        log::info!("Build failed.");
        return;
    }

    log::debug!("Fuzzing `{module}`.");
    let db = Database::default();
    fuzzer::fuzz(&db, module).await;
}

async fn lsp() {
    log::info!("Starting language server…");
    let (service, socket) = LspService::new(CandyLanguageServer::from_client);
    Server::new(tokio::io::stdin(), tokio::io::stdout(), socket)
        .serve(service)
        .await;
}

fn init_logger() {
    let colors = ColoredLevelConfig::new().debug(Color::BrightBlack);
    fern::Dispatch::new()
        .format(move |out, message, record| {
            let color = colors.get_color(&record.level());
            out.finish(format_args!(
                "\x1B[{}m{} [{:>5}] {} {}\x1B[0m",
                color.to_fg_str(),
                chrono::Local::now().format("%H:%M:%S"),
                record.level(),
                record.target(),
                message
            ))
        })
        .level_for("candy::compiler::hir_to_lir", LevelFilter::Debug)
        .level_for("candy::compiler::string_to_rcst", LevelFilter::Debug)
        .level_for("candy::language_server::hints", LevelFilter::Debug)
        .level_for("candy::vm::builtin_functions", LevelFilter::Warn)
        .level_for("candy::vm::heap", LevelFilter::Debug)
        .level_for("candy::vm::vm", LevelFilter::Info)
        .level_for("lspower::transport", LevelFilter::Error)
        .level_for("salsa", LevelFilter::Error)
        .level_for("tokio_util", LevelFilter::Error)
        .chain(std::io::stderr())
        .apply()
        .unwrap();
}
<commit_msg>Print result after running a module<commit_after>#![feature(async_closure)]
#![feature(box_patterns)]
#![feature(label_break_value)]
#![feature(never_type)]
#![feature(try_trait_v2)]
#![allow(clippy::module_inception)]

mod builtin_functions;
mod compiler;
mod database;
mod fuzzer;
mod language_server;
mod module;
mod vm;

use crate::{
    compiler::{
        ast_to_hir::AstToHir,
        cst_to_ast::CstToAst,
        error::CompilerError,
        hir::{self, CollectErrors},
        hir_to_lir::HirToLir,
        rcst_to_cst::RcstToCst,
        string_to_rcst::StringToRcst,
    },
    database::Database,
    language_server::utils::LspPositionConversion,
    module::{Module, ModuleKind},
    vm::{use_provider::DbUseProvider, Closure, TearDownResult, Vm},
};
use compiler::lir::Lir;
use fern::colors::{Color, ColoredLevelConfig};
use itertools::Itertools;
use language_server::CandyLanguageServer;
use log::{self, LevelFilter};
use notify::{watcher, RecursiveMode, Watcher};
use std::{
    env::current_dir,
    fs,
    path::PathBuf,
    sync::{mpsc::channel, Arc},
    time::Duration,
};
use structopt::StructOpt;
use tower_lsp::{LspService, Server};

#[derive(StructOpt, Debug)]
#[structopt(name = "candy", about = "The 🍭 Candy CLI.")]
enum CandyOptions {
    Build(CandyBuildOptions),
    Run(CandyRunOptions),
    Fuzz(CandyFuzzOptions),
    Lsp,
}

#[derive(StructOpt, Debug)]
struct CandyBuildOptions {
    #[structopt(long)]
    debug: bool,

    #[structopt(long)]
    watch: bool,

    #[structopt(parse(from_os_str))]
    file: PathBuf,
}

#[derive(StructOpt, Debug)]
struct CandyRunOptions {
    #[structopt(long)]
    debug: bool,

    #[structopt(parse(from_os_str))]
    file: PathBuf,
}

#[derive(StructOpt, Debug)]
struct CandyFuzzOptions {
    #[structopt(parse(from_os_str))]
    file: PathBuf,
}

#[tokio::main]
async fn main() {
    init_logger();
    match CandyOptions::from_args() {
        CandyOptions::Build(options) => build(options),
        CandyOptions::Run(options) => run(options),
        CandyOptions::Fuzz(options) => fuzz(options).await,
        CandyOptions::Lsp => lsp().await,
    }
}

fn build(options: CandyBuildOptions) {
    let module = Module::from_package_root_and_file(
        current_dir().unwrap(),
        options.file.clone(),
        ModuleKind::Code,
    );
    raw_build(module.clone(), options.debug);

    if options.watch {
        let (tx, rx) = channel();
        let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
        watcher
            .watch(&options.file, RecursiveMode::Recursive)
            .unwrap();
        loop {
            match rx.recv() {
                Ok(_) => {
                    raw_build(module.clone(), options.debug);
                }
                Err(e) => log::error!("watch error: {e:#?}"),
            }
        }
    }
}
fn raw_build(module: Module, debug: bool) -> Option<Arc<Lir>> {
    log::info!("Building `{module}`.");

    let db = Database::default();

    log::debug!("Parsing string to RCST…");
    let rcst = db
        .rcst(module.clone())
        .unwrap_or_else(|err| panic!("Error parsing file `{}`: {:?}", module, err));
    if debug {
        let rcst_file = module.associated_debug_file("rcst");
        fs::write(rcst_file, format!("{:#?}\n", rcst)).unwrap();
    }

    log::debug!("Turning RCST to CST…");
    let cst = db.cst(module.clone()).unwrap();
    if debug {
        let cst_file = module.associated_debug_file("cst");
        fs::write(cst_file, format!("{:#?}\n", cst)).unwrap();
    }

    log::debug!("Abstracting CST to AST…");
    let (asts, ast_cst_id_map) = db.ast(module.clone()).unwrap();
    if debug {
        let ast_file = module.associated_debug_file("ast");
        fs::write(
            ast_file,
            format!("{}\n", asts.iter().map(|ast| format!("{}", ast)).join("\n")),
        )
        .unwrap();

        let ast_to_cst_ids_file = module.associated_debug_file("ast_to_cst_ids");
        fs::write(
            ast_to_cst_ids_file,
            ast_cst_id_map
                .keys()
                .into_iter()
                .sorted_by_key(|it| it.local)
                .map(|key| format!("{key} -> {}\n", ast_cst_id_map[key].0))
                .join(""),
        )
        .unwrap();
    }

    log::debug!("Turning AST to HIR…");
    let (hir, hir_ast_id_map) = db.hir(module.clone()).unwrap();
    if debug {
        let hir_file = module.associated_debug_file("hir");
        fs::write(hir_file, format!("{}", hir)).unwrap();

        let hir_ast_id_file = module.associated_debug_file("hir_to_ast_ids");
        fs::write(
            hir_ast_id_file,
            hir_ast_id_map
                .keys()
                .into_iter()
                .map(|key| format!("{key} -> {}\n", hir_ast_id_map[key]))
                .join(""),
        )
        .unwrap();
    }

    log::debug!("Lowering HIR to LIR…");
    let lir = db.lir(module.clone()).unwrap();
    if debug {
        let lir_file = module.associated_debug_file("lir");
        fs::write(lir_file, format!("{lir}")).unwrap();
    }

    let mut errors = vec![];
    hir.collect_errors(&mut errors);
    for CompilerError { span, payload, .. } in errors {
        let (start_line, start_col) = db.offset_to_lsp(module.clone(), span.start);
        let (end_line, end_col) = db.offset_to_lsp(module.clone(), span.end);
        log::warn!("{start_line}:{start_col} – {end_line}:{end_col}: {payload:?}");
    }

    Some(lir)
}

fn run(options: CandyRunOptions) {
    let module = Module::from_package_root_and_file(
        current_dir().unwrap(),
        options.file.clone(),
        ModuleKind::Code,
    );
    let db = Database::default();

    if raw_build(module.clone(), false).is_none() {
        log::info!("Build failed.");
        return;
    };
    let module_closure = Closure::of_module(&db, module.clone()).unwrap();

    let path_string = options.file.to_string_lossy();
    log::info!("Running `{path_string}`.");

    let use_provider = DbUseProvider { db: &db };
    let vm = Vm::new_for_running_module_closure(&use_provider, module_closure);
    let TearDownResult {
        tracer,
        result,
        heap,
        ..
    } = vm.run_synchronously_until_completion(&db);

    match result {
        Ok(return_value) => log::info!(
            "The module exports these definitions: {}",
            return_value.format(&heap)
        ),
        Err(reason) => {
            log::error!("The module panicked because {reason}.");
            log::error!("This is the stack trace:");
            tracer.dump_stack_trace(&db, &heap);
        }
    }

    if options.debug {
        let trace = tracer.dump_call_tree();
        let trace_file = module.associated_debug_file("trace");
        fs::write(trace_file.clone(), trace).unwrap();
        log::info!(
            "Trace has been written to `{}`.",
            trace_file.as_path().display()
        );
    }
}

async fn fuzz(options: CandyFuzzOptions) {
    let module = Module::from_package_root_and_file(
        current_dir().unwrap(),
        options.file.clone(),
        ModuleKind::Code,
    );
    log::debug!("Building `{}`.\n", module);

    if raw_build(module.clone(), false).is_none() {
        log::info!("Build failed.");
        return;
    }

    log::debug!("Fuzzing `{module}`.");
    let db = Database::default();
    fuzzer::fuzz(&db, module).await;
}

async fn lsp() {
    log::info!("Starting language server…");
    let (service, socket) = LspService::new(CandyLanguageServer::from_client);
    Server::new(tokio::io::stdin(), tokio::io::stdout(), socket)
        .serve(service)
        .await;
}

fn init_logger() {
    let colors = ColoredLevelConfig::new().debug(Color::BrightBlack);
    fern::Dispatch::new()
        .format(move |out, message, record| {
            let color = colors.get_color(&record.level());
            out.finish(format_args!(
                "\x1B[{}m{} [{:>5}] {} {}\x1B[0m",
                color.to_fg_str(),
                chrono::Local::now().format("%H:%M:%S"),
                record.level(),
                record.target(),
                message
            ))
        })
        .level_for("candy::compiler::hir_to_lir", LevelFilter::Debug)
        .level_for("candy::compiler::string_to_rcst", LevelFilter::Debug)
        .level_for("candy::language_server::hints", LevelFilter::Debug)
        .level_for("candy::vm::builtin_functions", LevelFilter::Warn)
        .level_for("candy::vm::heap", LevelFilter::Debug)
        .level_for("candy::vm::vm", LevelFilter::Info)
        .level_for("lspower::transport", LevelFilter::Error)
        .level_for("salsa", LevelFilter::Error)
        .level_for("tokio_util", LevelFilter::Error)
        .chain(std::io::stderr())
        .apply()
        .unwrap();
}
<|endoftext|>


<commit_before>// Copyright 2015 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use bincode::serde::DeserializeError;
use std::sync::mpsc;
use std::sync::{Arc, Mutex};
use std::collections::hash_map::HashMap;
use std::cell::{RefCell};
use std::io::{Error, ErrorKind};
use std::slice;
use std::fmt::{self, Debug, Formatter};
use std::cmp::{PartialEq};
use std::ops::Deref;
use std::mem;
use std::usize;

use uuid::Uuid;

#[derive(Clone)]
struct ServerRecord {
    sender: OsIpcSender,
    conn_sender: mpsc::Sender<bool>,
    conn_receiver: Arc<Mutex<mpsc::Receiver<bool>>>,
}

impl ServerRecord {
    fn new(sender: OsIpcSender) -> ServerRecord {
        let (tx, rx) = mpsc::channel::<bool>();
        ServerRecord {
            sender: sender,
            conn_sender: tx,
            conn_receiver: Arc::new(Mutex::new(rx)),
        }
    }

    fn accept(&self) {
        self.conn_receiver.lock().unwrap().recv().unwrap();
    }

    fn connect(&self) {
        self.conn_sender.send(true).unwrap();
    }
}

lazy_static! {
    static ref ONE_SHOT_SERVERS: Mutex<HashMap<String,ServerRecord>> = Mutex::new(HashMap::new());
}

struct MpscChannelMessage(Vec<u8>, Vec<OsIpcChannel>, Vec<OsIpcSharedMemory>);

pub fn channel() -> Result<(OsIpcSender, OsIpcReceiver),MpscError> {
    let (base_sender, base_receiver) = mpsc::channel::<MpscChannelMessage>();
    Ok((OsIpcSender::new(base_sender), OsIpcReceiver::new(base_receiver)))
}

#[derive(Debug)]
pub struct OsIpcReceiver {
    receiver: RefCell<Option<mpsc::Receiver<MpscChannelMessage>>>,
}

impl PartialEq for OsIpcReceiver {
    fn eq(&self, other: &OsIpcReceiver) -> bool {
        self.receiver.borrow().as_ref().map(|rx| rx as *const _) ==
            other.receiver.borrow().as_ref().map(|rx| rx as *const _)
    }
}

impl OsIpcReceiver {
    fn new(receiver: mpsc::Receiver<MpscChannelMessage>) -> OsIpcReceiver {
        OsIpcReceiver {
            receiver: RefCell::new(Some(receiver)),
        }
    }

    pub fn consume(&self) -> OsIpcReceiver {
        let receiver = self.receiver.borrow_mut().take();
        OsIpcReceiver::new(receiver.unwrap())
    }

    pub fn recv(&self) -> Result<(Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OsOpaqueIpcChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }

    pub fn try_recv(&self) -> Result<(Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().try_recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OsOpaqueIpcChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }
}

#[derive(Clone, Debug)]
pub struct OsIpcSender {
    sender: Arc<Mutex<mpsc::Sender<MpscChannelMessage>>>,
}

impl PartialEq for OsIpcSender {
    fn eq(&self, other: &OsIpcSender) -> bool {
        &*self.sender.lock().unwrap() as *const _ ==
            &*other.sender.lock().unwrap() as *const _
    }
}

impl OsIpcSender {
    fn new(sender: mpsc::Sender<MpscChannelMessage>) -> OsIpcSender {
        OsIpcSender {
            sender: Arc::new(Mutex::new(sender)),
        }
    }

    pub fn connect(name: String) -> Result<OsIpcSender,MpscError> {
        let record = ONE_SHOT_SERVERS.lock().unwrap().get(&name).unwrap().clone();
        record.connect();
        Ok(record.sender)
    }

    pub fn get_max_fragment_size() -> usize {
        usize::MAX
    }

    pub fn send(&self,
                data: &[u8],
                ports: Vec<OsIpcChannel>,
                shared_memory_regions: Vec<OsIpcSharedMemory>)
                -> Result<(),MpscError>
    {
        match self.sender.lock().unwrap().send(MpscChannelMessage(data.to_vec(), ports, shared_memory_regions)) {
            Err(_) => Err(MpscError::ChannelClosedError),
            Ok(_) => Ok(()),
        }
    }
}

pub struct OsIpcReceiverSet {
    last_index: usize,
    receiver_ids: Vec<usize>,
    receivers: Vec<OsIpcReceiver>,
}

impl OsIpcReceiverSet {
    pub fn new() -> Result<OsIpcReceiverSet,MpscError> {
        Ok(OsIpcReceiverSet {
            last_index: 0,
            receiver_ids: vec![],
            receivers: vec![],
        })
    }

    pub fn add(&mut self, receiver: OsIpcReceiver) -> Result<i64,MpscError> {
        self.last_index += 1;
        self.receiver_ids.push(self.last_index);
        self.receivers.push(receiver.consume());
        Ok(self.last_index as i64)
    }

    pub fn select(&mut self) -> Result<Vec<OsIpcSelectionResult>,MpscError> {
        let mut receivers: Vec<Option<mpsc::Receiver<MpscChannelMessage>>> = Vec::with_capacity(self.receivers.len());
        let mut r_id: i64 = -1;
        let mut r_index: usize = 0;

        {
            let select = mpsc::Select::new();
            // we *must* allocate exact capacity for this, because the Handles *can't move*
            let mut handles: Vec<mpsc::Handle<MpscChannelMessage>> = Vec::with_capacity(self.receivers.len());

            for r in &self.receivers {
                let inner_r = mem::replace(&mut *r.receiver.borrow_mut(), None);
                receivers.push(inner_r);
            }

            for r in &receivers {
                unsafe {
                    handles.push(select.handle(r.as_ref().unwrap()));
                    handles.last_mut().unwrap().add();
                }
            }

            let id = select.wait();

            for (index,h) in handles.iter().enumerate() {
                if h.id() == id {
                    r_index = index;
                    r_id = self.receiver_ids[index] as i64;
                    break;
                }
            }
        }

        // put the receivers back
        for (index,r) in self.receivers.iter().enumerate() {
            mem::replace(&mut *r.receiver.borrow_mut(), mem::replace(&mut receivers[index], None));
        }

        if r_id == -1 {
            return Err(MpscError::UnknownError);
        }

        let receivers = &mut self.receivers;
        match receivers[r_index].recv() {
            Ok((data, channels, shmems)) =>
                Ok(vec![OsIpcSelectionResult::DataReceived(r_id, data, channels, shmems)]),
            Err(MpscError::ChannelClosedError) => {
                receivers.remove(r_index);
                self.receiver_ids.remove(r_index);
                Ok(vec![OsIpcSelectionResult::ChannelClosed(r_id)])
            },
            Err(err) => Err(err),
        }
    }
}

pub enum OsIpcSelectionResult {
    DataReceived(i64, Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),
    ChannelClosed(i64),
}

impl OsIpcSelectionResult {
    pub fn unwrap(self) -> (i64, Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>) {
        match self {
            OsIpcSelectionResult::DataReceived(id, data, channels, shared_memory_regions) => {
                (id, data, channels, shared_memory_regions)
            }
            OsIpcSelectionResult::ChannelClosed(id) => {
                panic!("OsIpcSelectionResult::unwrap(): receiver ID {} was closed!", id)
            }
        }
    }
}

pub struct OsIpcOneShotServer {
    receiver: Option<OsIpcReceiver>,
    name: String,
}

impl OsIpcOneShotServer {
    pub fn new() -> Result<(OsIpcOneShotServer, String),MpscError> {
        let (sender, receiver) = try!(channel());

        let name = Uuid::new_v4().to_string();
        let record = ServerRecord::new(sender);
        ONE_SHOT_SERVERS.lock().unwrap().insert(name.clone(), record);
        Ok((OsIpcOneShotServer {
            receiver: Some(receiver),
            name: name.clone(),
        },name.clone()))
    }

    pub fn accept(mut self) -> Result<(OsIpcReceiver,
                                    Vec<u8>,
                                    Vec<OsOpaqueIpcChannel>,
                                    Vec<OsIpcSharedMemory>),MpscError>
    {
        let record = ONE_SHOT_SERVERS.lock().unwrap().get(&self.name).unwrap().clone();
        record.accept();
        ONE_SHOT_SERVERS.lock().unwrap().remove(&self.name).unwrap();
        let receiver = self.receiver.take().unwrap();
        let (data, channels, shmems) = receiver.recv().unwrap();
        Ok((receiver, data, channels, shmems))
    }
}

#[derive(PartialEq, Debug)]
pub enum OsIpcChannel {
    Sender(OsIpcSender),
    Receiver(OsIpcReceiver),
}

#[derive(PartialEq, Debug)]
pub struct OsOpaqueIpcChannel {
    channel: RefCell<Option<OsIpcChannel>>,
}

impl OsOpaqueIpcChannel {
    fn new(channel: OsIpcChannel) -> OsOpaqueIpcChannel {
        OsOpaqueIpcChannel {
            channel: RefCell::new(Some(channel))
        }
    }

    pub fn to_receiver(&self) -> OsIpcReceiver {
        match self.channel.borrow_mut().take().unwrap() {
            OsIpcChannel::Sender(_) => panic!("Opaque channel is not a receiver!"),
            OsIpcChannel::Receiver(r) => r
        }
    }

    pub fn to_sender(&mut self) -> OsIpcSender {
        match self.channel.borrow_mut().take().unwrap() {
            OsIpcChannel::Sender(s) => s,
            OsIpcChannel::Receiver(_) => panic!("Opaque channel is not a sender!"),
        }
    }
}

pub struct OsIpcSharedMemory {
    ptr: *mut u8,
    length: usize,
    data: Arc<Vec<u8>>,
}

unsafe impl Send for OsIpcSharedMemory {}
unsafe impl Sync for OsIpcSharedMemory {}

impl Clone for OsIpcSharedMemory {
    fn clone(&self) -> OsIpcSharedMemory {
        OsIpcSharedMemory {
            ptr: self.ptr,
            length: self.length,
            data: self.data.clone(),
        }
    }
}

impl PartialEq for OsIpcSharedMemory {
    fn eq(&self, other: &OsIpcSharedMemory) -> bool {
        **self == **other
    }
}

impl Debug for OsIpcSharedMemory {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        (**self).fmt(formatter)
    }
}

impl Deref for OsIpcSharedMemory {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        if self.ptr.is_null() {
            panic!("attempted to access a consumed `OsIpcSharedMemory`")
        }
        unsafe {
            slice::from_raw_parts(self.ptr, self.length)
        }
    }
}

impl OsIpcSharedMemory {
    pub fn from_byte(byte: u8, length: usize) -> OsIpcSharedMemory {
        let mut v = Arc::new(vec![byte; length]);
        OsIpcSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: length,
            data: v
        }
    }

    pub fn from_bytes(bytes: &[u8]) -> OsIpcSharedMemory {
        let mut v = Arc::new(bytes.to_vec());
        OsIpcSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: v.len(),
            data: v
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum MpscError {
    ChannelClosedError,
    UnknownError,
}

impl MpscError {
    #[allow(dead_code)]
    pub fn channel_is_closed(&self) -> bool {
        *self == MpscError::ChannelClosedError
    }
}

impl From<MpscError> for DeserializeError {
    fn from(mpsc_error: MpscError) -> DeserializeError {
        DeserializeError::IoError(mpsc_error.into())
    }
}

impl From<MpscError> for Error {
    fn from(mpsc_error: MpscError) -> Error {
        match mpsc_error {
            MpscError::ChannelClosedError => {
                Error::new(ErrorKind::BrokenPipe, "MPSC channel closed")
            }
            MpscError::UnknownError => Error::new(ErrorKind::Other, "Other MPSC channel error"),
        }
    }
}

<commit_msg>Cleanup: inprocess: Avoid unneeded `Option<>`<commit_after>// Copyright 2015 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use bincode::serde::DeserializeError;
use std::sync::mpsc;
use std::sync::{Arc, Mutex};
use std::collections::hash_map::HashMap;
use std::cell::{RefCell};
use std::io::{Error, ErrorKind};
use std::slice;
use std::fmt::{self, Debug, Formatter};
use std::cmp::{PartialEq};
use std::ops::Deref;
use std::mem;
use std::usize;

use uuid::Uuid;

#[derive(Clone)]
struct ServerRecord {
    sender: OsIpcSender,
    conn_sender: mpsc::Sender<bool>,
    conn_receiver: Arc<Mutex<mpsc::Receiver<bool>>>,
}

impl ServerRecord {
    fn new(sender: OsIpcSender) -> ServerRecord {
        let (tx, rx) = mpsc::channel::<bool>();
        ServerRecord {
            sender: sender,
            conn_sender: tx,
            conn_receiver: Arc::new(Mutex::new(rx)),
        }
    }

    fn accept(&self) {
        self.conn_receiver.lock().unwrap().recv().unwrap();
    }

    fn connect(&self) {
        self.conn_sender.send(true).unwrap();
    }
}

lazy_static! {
    static ref ONE_SHOT_SERVERS: Mutex<HashMap<String,ServerRecord>> = Mutex::new(HashMap::new());
}

struct MpscChannelMessage(Vec<u8>, Vec<OsIpcChannel>, Vec<OsIpcSharedMemory>);

pub fn channel() -> Result<(OsIpcSender, OsIpcReceiver),MpscError> {
    let (base_sender, base_receiver) = mpsc::channel::<MpscChannelMessage>();
    Ok((OsIpcSender::new(base_sender), OsIpcReceiver::new(base_receiver)))
}

#[derive(Debug)]
pub struct OsIpcReceiver {
    receiver: RefCell<Option<mpsc::Receiver<MpscChannelMessage>>>,
}

impl PartialEq for OsIpcReceiver {
    fn eq(&self, other: &OsIpcReceiver) -> bool {
        self.receiver.borrow().as_ref().map(|rx| rx as *const _) ==
            other.receiver.borrow().as_ref().map(|rx| rx as *const _)
    }
}

impl OsIpcReceiver {
    fn new(receiver: mpsc::Receiver<MpscChannelMessage>) -> OsIpcReceiver {
        OsIpcReceiver {
            receiver: RefCell::new(Some(receiver)),
        }
    }

    pub fn consume(&self) -> OsIpcReceiver {
        let receiver = self.receiver.borrow_mut().take();
        OsIpcReceiver::new(receiver.unwrap())
    }

    pub fn recv(&self) -> Result<(Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OsOpaqueIpcChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }

    pub fn try_recv(&self) -> Result<(Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().try_recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OsOpaqueIpcChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }
}

#[derive(Clone, Debug)]
pub struct OsIpcSender {
    sender: Arc<Mutex<mpsc::Sender<MpscChannelMessage>>>,
}

impl PartialEq for OsIpcSender {
    fn eq(&self, other: &OsIpcSender) -> bool {
        &*self.sender.lock().unwrap() as *const _ ==
            &*other.sender.lock().unwrap() as *const _
    }
}

impl OsIpcSender {
    fn new(sender: mpsc::Sender<MpscChannelMessage>) -> OsIpcSender {
        OsIpcSender {
            sender: Arc::new(Mutex::new(sender)),
        }
    }

    pub fn connect(name: String) -> Result<OsIpcSender,MpscError> {
        let record = ONE_SHOT_SERVERS.lock().unwrap().get(&name).unwrap().clone();
        record.connect();
        Ok(record.sender)
    }

    pub fn get_max_fragment_size() -> usize {
        usize::MAX
    }

    pub fn send(&self,
                data: &[u8],
                ports: Vec<OsIpcChannel>,
                shared_memory_regions: Vec<OsIpcSharedMemory>)
                -> Result<(),MpscError>
    {
        match self.sender.lock().unwrap().send(MpscChannelMessage(data.to_vec(), ports, shared_memory_regions)) {
            Err(_) => Err(MpscError::ChannelClosedError),
            Ok(_) => Ok(()),
        }
    }
}

pub struct OsIpcReceiverSet {
    last_index: usize,
    receiver_ids: Vec<usize>,
    receivers: Vec<OsIpcReceiver>,
}

impl OsIpcReceiverSet {
    pub fn new() -> Result<OsIpcReceiverSet,MpscError> {
        Ok(OsIpcReceiverSet {
            last_index: 0,
            receiver_ids: vec![],
            receivers: vec![],
        })
    }

    pub fn add(&mut self, receiver: OsIpcReceiver) -> Result<i64,MpscError> {
        self.last_index += 1;
        self.receiver_ids.push(self.last_index);
        self.receivers.push(receiver.consume());
        Ok(self.last_index as i64)
    }

    pub fn select(&mut self) -> Result<Vec<OsIpcSelectionResult>,MpscError> {
        let mut receivers: Vec<Option<mpsc::Receiver<MpscChannelMessage>>> = Vec::with_capacity(self.receivers.len());
        let mut r_id: i64 = -1;
        let mut r_index: usize = 0;

        {
            let select = mpsc::Select::new();
            // we *must* allocate exact capacity for this, because the Handles *can't move*
            let mut handles: Vec<mpsc::Handle<MpscChannelMessage>> = Vec::with_capacity(self.receivers.len());

            for r in &self.receivers {
                let inner_r = mem::replace(&mut *r.receiver.borrow_mut(), None);
                receivers.push(inner_r);
            }

            for r in &receivers {
                unsafe {
                    handles.push(select.handle(r.as_ref().unwrap()));
                    handles.last_mut().unwrap().add();
                }
            }

            let id = select.wait();

            for (index,h) in handles.iter().enumerate() {
                if h.id() == id {
                    r_index = index;
                    r_id = self.receiver_ids[index] as i64;
                    break;
                }
            }
        }

        // put the receivers back
        for (index,r) in self.receivers.iter().enumerate() {
            mem::replace(&mut *r.receiver.borrow_mut(), mem::replace(&mut receivers[index], None));
        }

        if r_id == -1 {
            return Err(MpscError::UnknownError);
        }

        let receivers = &mut self.receivers;
        match receivers[r_index].recv() {
            Ok((data, channels, shmems)) =>
                Ok(vec![OsIpcSelectionResult::DataReceived(r_id, data, channels, shmems)]),
            Err(MpscError::ChannelClosedError) => {
                receivers.remove(r_index);
                self.receiver_ids.remove(r_index);
                Ok(vec![OsIpcSelectionResult::ChannelClosed(r_id)])
            },
            Err(err) => Err(err),
        }
    }
}

pub enum OsIpcSelectionResult {
    DataReceived(i64, Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),
    ChannelClosed(i64),
}

impl OsIpcSelectionResult {
    pub fn unwrap(self) -> (i64, Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>) {
        match self {
            OsIpcSelectionResult::DataReceived(id, data, channels, shared_memory_regions) => {
                (id, data, channels, shared_memory_regions)
            }
            OsIpcSelectionResult::ChannelClosed(id) => {
                panic!("OsIpcSelectionResult::unwrap(): receiver ID {} was closed!", id)
            }
        }
    }
}

pub struct OsIpcOneShotServer {
    receiver: OsIpcReceiver,
    name: String,
}

impl OsIpcOneShotServer {
    pub fn new() -> Result<(OsIpcOneShotServer, String),MpscError> {
        let (sender, receiver) = try!(channel());

        let name = Uuid::new_v4().to_string();
        let record = ServerRecord::new(sender);
        ONE_SHOT_SERVERS.lock().unwrap().insert(name.clone(), record);
        Ok((OsIpcOneShotServer {
            receiver: receiver,
            name: name.clone(),
        },name.clone()))
    }

    pub fn accept(self) -> Result<(OsIpcReceiver,
                                    Vec<u8>,
                                    Vec<OsOpaqueIpcChannel>,
                                    Vec<OsIpcSharedMemory>),MpscError>
    {
        let record = ONE_SHOT_SERVERS.lock().unwrap().get(&self.name).unwrap().clone();
        record.accept();
        ONE_SHOT_SERVERS.lock().unwrap().remove(&self.name).unwrap();
        let (data, channels, shmems) = self.receiver.recv().unwrap();
        Ok((self.receiver, data, channels, shmems))
    }
}

#[derive(PartialEq, Debug)]
pub enum OsIpcChannel {
    Sender(OsIpcSender),
    Receiver(OsIpcReceiver),
}

#[derive(PartialEq, Debug)]
pub struct OsOpaqueIpcChannel {
    channel: RefCell<Option<OsIpcChannel>>,
}

impl OsOpaqueIpcChannel {
    fn new(channel: OsIpcChannel) -> OsOpaqueIpcChannel {
        OsOpaqueIpcChannel {
            channel: RefCell::new(Some(channel))
        }
    }

    pub fn to_receiver(&self) -> OsIpcReceiver {
        match self.channel.borrow_mut().take().unwrap() {
            OsIpcChannel::Sender(_) => panic!("Opaque channel is not a receiver!"),
            OsIpcChannel::Receiver(r) => r
        }
    }

    pub fn to_sender(&mut self) -> OsIpcSender {
        match self.channel.borrow_mut().take().unwrap() {
            OsIpcChannel::Sender(s) => s,
            OsIpcChannel::Receiver(_) => panic!("Opaque channel is not a sender!"),
        }
    }
}

pub struct OsIpcSharedMemory {
    ptr: *mut u8,
    length: usize,
    data: Arc<Vec<u8>>,
}

unsafe impl Send for OsIpcSharedMemory {}
unsafe impl Sync for OsIpcSharedMemory {}

impl Clone for OsIpcSharedMemory {
    fn clone(&self) -> OsIpcSharedMemory {
        OsIpcSharedMemory {
            ptr: self.ptr,
            length: self.length,
            data: self.data.clone(),
        }
    }
}

impl PartialEq for OsIpcSharedMemory {
    fn eq(&self, other: &OsIpcSharedMemory) -> bool {
        **self == **other
    }
}

impl Debug for OsIpcSharedMemory {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        (**self).fmt(formatter)
    }
}

impl Deref for OsIpcSharedMemory {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        if self.ptr.is_null() {
            panic!("attempted to access a consumed `OsIpcSharedMemory`")
        }
        unsafe {
            slice::from_raw_parts(self.ptr, self.length)
        }
    }
}

impl OsIpcSharedMemory {
    pub fn from_byte(byte: u8, length: usize) -> OsIpcSharedMemory {
        let mut v = Arc::new(vec![byte; length]);
        OsIpcSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: length,
            data: v
        }
    }

    pub fn from_bytes(bytes: &[u8]) -> OsIpcSharedMemory {
        let mut v = Arc::new(bytes.to_vec());
        OsIpcSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: v.len(),
            data: v
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum MpscError {
    ChannelClosedError,
    UnknownError,
}

impl MpscError {
    #[allow(dead_code)]
    pub fn channel_is_closed(&self) -> bool {
        *self == MpscError::ChannelClosedError
    }
}

impl From<MpscError> for DeserializeError {
    fn from(mpsc_error: MpscError) -> DeserializeError {
        DeserializeError::IoError(mpsc_error.into())
    }
}

impl From<MpscError> for Error {
    fn from(mpsc_error: MpscError) -> Error {
        match mpsc_error {
            MpscError::ChannelClosedError => {
                Error::new(ErrorKind::BrokenPipe, "MPSC channel closed")
            }
            MpscError::UnknownError => Error::new(ErrorKind::Other, "Other MPSC channel error"),
        }
    }
}

<|endoftext|>


<commit_before><commit_msg>Reorganized the elb_log_files file to bring the public API to the top of the file.<commit_after><|endoftext|>


<commit_before><commit_msg>login: autofill username if there is only one normal user<commit_after><|endoftext|>


<commit_before>// 定义一个函数，可以接受另一个函数作为参数并调用它。
fn call_function<F: Fn()>(f: F) {
    f()
}

// 定义一个简单的函数用作输入量。
fn print() {
    println!("I'm a function!")
}

fn main() {
    // 定义一个和上面的 `print()` 函数类似的闭包。
    let closure = || println!("I'm a closure!");

    call_function(closure);
    call_function(print);
}
<commit_msg>Refactor names and comments<commit_after>// 定义一个函数，可以接受一个由 `Fn` 限定的泛型 `F` 参数并调用它。
fn call_me<F: Fn()>(f: F) {
    f()
}

// 定义一个满足 `Fn` 限定的装包函数（wrapper function）。
fn function() {
    println!("I'm a function!")
}

fn main() {
    // 定义一个满足 `Fn` 限定的闭包。
    let closure = || println!("I'm a closure!");

    call_me(closure);
    call_me(function);
}
<|endoftext|>


<commit_before>extern crate libc;

use core::Workspaces;
use window_manager::WindowManager;
use window_system::WindowSystem;
use window_system::Window;
use config::{ GeneralConfig, Config };

pub type KeyHandler<'a> = Box<Fn<(WindowManager<'a>, &'a (WindowSystem + 'a), &'a GeneralConfig<'a>), WindowManager<'a>> + 'a>;
pub type MouseHandler<'a> = Box<Fn<(WindowManager<'a>, &'a (WindowSystem + 'a), &'a GeneralConfig<'a>, Window), WindowManager<'a>> + 'a>;
pub type ManageHook<'a> = Box<Fn<(Workspaces<'a>, &'a (WindowSystem + 'a), Window), Workspaces<'a>> + 'a>;
pub type StartupHook<'a> = Box<Fn<(WindowManager<'a>, &'a (WindowSystem + 'a), &'a Config<'a>), WindowManager<'a>> + 'a>;
pub type LogHook<'a> = Box<FnMut<(WindowManager<'a>, &'a (WindowSystem + 'a)), ()> + 'a>;

extern {
    pub fn waitpid(fd: libc::pid_t, status: *mut libc::c_int, options: libc::c_int) -> libc::pid_t;
}

/// Some default handlers for easier config scripts
pub mod default {
    use std::os;
    use std::ptr::null;
    use std::io::process::Command;
    use std::thread::Thread;
    use serialize::json;
    use core::Workspaces;
    use window_manager::WindowManager;
    use window_system::WindowSystem;
    use window_system::Window;
    use config::GeneralConfig;
    use handlers::libc::funcs::posix88::unistd::execvp;

    pub fn start_terminal<'a>(window_manager: WindowManager<'a>, _: &WindowSystem,
                          config: &GeneralConfig) -> WindowManager<'a> {
        let (terminal, args) = config.terminal.clone();
        let arguments : Vec<String> = if args.is_empty() {
            Vec::new()
        } else {
            args.split(' ').map(String::from_str).collect()
        };

        Thread::spawn(move || {
            debug!("spawning terminal");
            let command = if arguments.is_empty() {
                Command::new(terminal).detached().spawn()
            } else {
                Command::new(terminal).args(arguments.as_slice()).detached().spawn()
            };

            if let Err(_) = command {
                panic!("unable to start terminal")
            }
        }).detach();

        window_manager.clone()
    }

    pub fn start_launcher<'a>(window_manager: WindowManager<'a>, _: &WindowSystem,
                          config: &GeneralConfig) -> WindowManager<'a> {
        let launcher = config.launcher.clone();
        Thread::spawn(move || {
            debug!("spawning launcher");
            match Command::new(launcher).detached().spawn() {
                Ok(_) => (),
                _     => panic!("unable to start launcher")
            }
        }).detach();

        window_manager.clone()
    }

    pub fn switch_to_workspace<'a>(window_manager: WindowManager<'a>, window_system: &WindowSystem,
                               config: &GeneralConfig<'a>, index: uint) -> WindowManager<'a> {
        window_manager.view(window_system, index as u32, config)
    }

    pub fn move_window_to_workspace<'a>(window_manager: WindowManager<'a>, window_system: &WindowSystem,
                                    config: &GeneralConfig<'a>, index: uint) -> WindowManager<'a> {
        window_manager.move_window_to_workspace(window_system, config, index as u32)
    }

    /// Restart the window manager by calling execvp and replacing the current binary
    /// with the new one in memory.
    /// Pass a list of all windows to it via command line arguments
    /// so it may resume work as usual.
    pub fn restart<'a>(window_manager: WindowManager<'a>, _: &WindowSystem, c: &GeneralConfig<'a>) -> WindowManager<'a> {
        // Get absolute path to binary
        let filename = os::make_absolute(&Path::new(os::args()[0].clone())).unwrap().to_c_str();
        // Collect all managed windows
        let window_ids : String = json::encode(&window_manager.workspaces.all_windows_with_workspaces());

        // Create arguments
        let program_name = os::args()[0].clone().to_c_str();
        let resume = String::from_str("--resume").to_c_str();
        let windows = window_ids.to_c_str();

        for ref p in c.pipes.iter() {
            match p.deref().write().unwrap().deref_mut().wait() {
                _ => ()
            }
        }

        unsafe {
            let mut slice : &mut [*const i8, ..4] = &mut [
                program_name.as_ptr(),
                resume.as_ptr(),
                windows.as_ptr(),
                null()
            ];
            execvp(filename.as_ptr(), slice.as_mut_ptr());
        }

        window_manager.clone()
    }

    /// Stop the window manager
    pub fn exit<'a>(w: WindowManager<'a>, _: &WindowSystem, _: &GeneralConfig<'a>) -> WindowManager<'a> {
        WindowManager { running: false, dragging: None, workspaces: w.workspaces }
    }

    pub fn shift<'a>(index: u32, workspace: Workspaces<'a>, window: Window) -> Workspaces<'a> {
        workspace.shift_window(index, window)
    }
}
<commit_msg>fallout - adapt array size syntax<commit_after>extern crate libc;

use core::Workspaces;
use window_manager::WindowManager;
use window_system::WindowSystem;
use window_system::Window;
use config::{ GeneralConfig, Config };

pub type KeyHandler<'a> = Box<Fn<(WindowManager<'a>, &'a (WindowSystem + 'a), &'a GeneralConfig<'a>), WindowManager<'a>> + 'a>;
pub type MouseHandler<'a> = Box<Fn<(WindowManager<'a>, &'a (WindowSystem + 'a), &'a GeneralConfig<'a>, Window), WindowManager<'a>> + 'a>;
pub type ManageHook<'a> = Box<Fn<(Workspaces<'a>, &'a (WindowSystem + 'a), Window), Workspaces<'a>> + 'a>;
pub type StartupHook<'a> = Box<Fn<(WindowManager<'a>, &'a (WindowSystem + 'a), &'a Config<'a>), WindowManager<'a>> + 'a>;
pub type LogHook<'a> = Box<FnMut<(WindowManager<'a>, &'a (WindowSystem + 'a)), ()> + 'a>;

extern {
    pub fn waitpid(fd: libc::pid_t, status: *mut libc::c_int, options: libc::c_int) -> libc::pid_t;
}

/// Some default handlers for easier config scripts
pub mod default {
    use std::os;
    use std::ptr::null;
    use std::io::process::Command;
    use std::thread::Thread;
    use serialize::json;
    use core::Workspaces;
    use window_manager::WindowManager;
    use window_system::WindowSystem;
    use window_system::Window;
    use config::GeneralConfig;
    use handlers::libc::funcs::posix88::unistd::execvp;

    pub fn start_terminal<'a>(window_manager: WindowManager<'a>, _: &WindowSystem,
                          config: &GeneralConfig) -> WindowManager<'a> {
        let (terminal, args) = config.terminal.clone();
        let arguments : Vec<String> = if args.is_empty() {
            Vec::new()
        } else {
            args.split(' ').map(String::from_str).collect()
        };

        Thread::spawn(move || {
            debug!("spawning terminal");
            let command = if arguments.is_empty() {
                Command::new(terminal).detached().spawn()
            } else {
                Command::new(terminal).args(arguments.as_slice()).detached().spawn()
            };

            if let Err(_) = command {
                panic!("unable to start terminal")
            }
        }).detach();

        window_manager.clone()
    }

    pub fn start_launcher<'a>(window_manager: WindowManager<'a>, _: &WindowSystem,
                          config: &GeneralConfig) -> WindowManager<'a> {
        let launcher = config.launcher.clone();
        Thread::spawn(move || {
            debug!("spawning launcher");
            match Command::new(launcher).detached().spawn() {
                Ok(_) => (),
                _     => panic!("unable to start launcher")
            }
        }).detach();

        window_manager.clone()
    }

    pub fn switch_to_workspace<'a>(window_manager: WindowManager<'a>, window_system: &WindowSystem,
                               config: &GeneralConfig<'a>, index: uint) -> WindowManager<'a> {
        window_manager.view(window_system, index as u32, config)
    }

    pub fn move_window_to_workspace<'a>(window_manager: WindowManager<'a>, window_system: &WindowSystem,
                                    config: &GeneralConfig<'a>, index: uint) -> WindowManager<'a> {
        window_manager.move_window_to_workspace(window_system, config, index as u32)
    }

    /// Restart the window manager by calling execvp and replacing the current binary
    /// with the new one in memory.
    /// Pass a list of all windows to it via command line arguments
    /// so it may resume work as usual.
    pub fn restart<'a>(window_manager: WindowManager<'a>, _: &WindowSystem, c: &GeneralConfig<'a>) -> WindowManager<'a> {
        // Get absolute path to binary
        let filename = os::make_absolute(&Path::new(os::args()[0].clone())).unwrap().to_c_str();
        // Collect all managed windows
        let window_ids : String = json::encode(&window_manager.workspaces.all_windows_with_workspaces());

        // Create arguments
        let program_name = os::args()[0].clone().to_c_str();
        let resume = String::from_str("--resume").to_c_str();
        let windows = window_ids.to_c_str();

        for ref p in c.pipes.iter() {
            match p.deref().write().unwrap().deref_mut().wait() {
                _ => ()
            }
        }

        unsafe {
            let mut slice : &mut [*const i8; 4] = &mut [
                program_name.as_ptr(),
                resume.as_ptr(),
                windows.as_ptr(),
                null()
            ];
            execvp(filename.as_ptr(), slice.as_mut_ptr());
        }

        window_manager.clone()
    }

    /// Stop the window manager
    pub fn exit<'a>(w: WindowManager<'a>, _: &WindowSystem, _: &GeneralConfig<'a>) -> WindowManager<'a> {
        WindowManager { running: false, dragging: None, workspaces: w.workspaces }
    }

    pub fn shift<'a>(index: u32, workspace: Workspaces<'a>, window: Window) -> Workspaces<'a> {
        workspace.shift_window(index, window)
    }
}
<|endoftext|>


<commit_before>use std::time::Duration;
use serde::{self, Deserialize, Serializer, Deserializer};

pub fn serialize<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer
{
    serializer.serialize_u64(duration.as_secs())
}

pub fn deserialize<D>(deserializer: D) -> Result<Duration, D::Error>
    where D: Deserializer
{
    let duration = u64::deserialize(deserializer)?;
    Ok(Duration::from_secs(duration))
}
<commit_msg>Remove unused import<commit_after>use std::time::Duration;
use serde::{Deserialize, Serializer, Deserializer};

pub fn serialize<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer
{
    serializer.serialize_u64(duration.as_secs())
}

pub fn deserialize<D>(deserializer: D) -> Result<Duration, D::Error>
    where D: Deserializer
{
    let duration = u64::deserialize(deserializer)?;
    Ok(Duration::from_secs(duration))
}
<|endoftext|>


<commit_before>use std::sync::RwLock;
use std::error::Error;

use iron::prelude::*;
use iron::{status};
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use plugin::Plugin as PluginFor;
use iron::headers::ContentType;

use handlebars::Handlebars;
use serialize::json::{ToJson, Json};

use ::source::{Source, SourceError};
use ::sources::directory::{DirectorySource};

#[derive(Clone)]
pub struct Template {
    name: String,
    value: Json
}

impl Template {
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: name.to_string(),
            value: value.to_json()
        }
    }
}

pub struct HandlebarsEngine {
    pub sources: Vec<Box<Source + Send + Sync>>,
    pub registry: RwLock<Box<Handlebars>>
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl PluginFor<Response> for HandlebarsEngine {
    type Error = ();

    fn eval(resp: &mut Response) -> Result<Template, ()> {
        match resp.extensions.get::<HandlebarsEngine>(){
            Some(t) => Ok(t.clone()),
            None => Err(())
        }
    }
}

impl HandlebarsEngine {
    /// #[Deprecated], for backward compaitibility only
    pub fn new(prefix: &str, suffix: &str) -> HandlebarsEngine {
        let mut hbs = HandlebarsEngine::new2();
        hbs.add(Box::new(DirectorySource::new(prefix, suffix)));
        hbs.reload();
        hbs
    }

    pub fn from(prefix: &str, suffix: &str, custom: Handlebars) -> HandlebarsEngine {
        let mut hbs = HandlebarsEngine::of(custom);
        hbs.add(Box::new(DirectorySource::new(prefix, suffix)));
        hbs.reload();
        hbs
    }

    pub fn new2() -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(Handlebars::new()))
        }
    }

    pub fn of(reg: Handlebars) -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(reg))
        }
    }

    pub fn add(&mut self, source: Box<Source + Send + Sync>) {
        self.sources.push(source);
    }

    #[allow(unused_must_use)]
    pub fn reload(&self) -> Result<(), SourceError> {
        let mut hbs = self.registry.write().unwrap();
        hbs.clear_templates();
        for s in self.sources.iter() {
            try!(s.load(&mut hbs))
        }
        Ok(())
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, r: Response) -> IronResult<Response> {
        let mut resp = r;
        let page_wrapper = resp.extensions.get::<HandlebarsEngine>().as_ref()
            .and_then(|h| {
                let hbs = self.registry.read().unwrap();
                Some(hbs.render(&h.name, &h.value))
            });

        match page_wrapper {
            Some(page_result) => {
                match page_result {
                    Ok(page) => {
                        if !resp.headers.has::<ContentType>() {
                            resp.headers.set(ContentType::html());
                        }
                        resp.set_mut(page);
                        Ok(resp)
                    }
                    Err(e) => {
                        info!("{}", e.description());
                        Err(IronError::new(e, status::InternalServerError))
                    }
                }
            }
            None => {
                Ok(resp)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use serialize::json::ToJson;
    use std::collections::BTreeMap;
    use iron::prelude::*;
    use middleware::*;
    use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};

    fn hello_world() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_string(), "Handlebars on Iron".to_json());

        Ok(resp.set(Template::new("index", data)))
    }

    #[test]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name, "index".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new2();
        let mut reg = hbs.registry.write().unwrap();
        reg.register_helper("ignore", Box::new(|_: &Context, _: &Helper, _: &Handlebars, _: &mut RenderContext| -> Result<(), RenderError> {
            Ok(())
        }));
    }
}
<commit_msg>(feat) of -> from2, mark from as deprecated<commit_after>use std::sync::RwLock;
use std::error::Error;

use iron::prelude::*;
use iron::{status};
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use plugin::Plugin as PluginFor;
use iron::headers::ContentType;

use handlebars::Handlebars;
use serialize::json::{ToJson, Json};

use ::source::{Source, SourceError};
use ::sources::directory::{DirectorySource};

#[derive(Clone)]
pub struct Template {
    name: String,
    value: Json
}

impl Template {
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: name.to_string(),
            value: value.to_json()
        }
    }
}

pub struct HandlebarsEngine {
    pub sources: Vec<Box<Source + Send + Sync>>,
    pub registry: RwLock<Box<Handlebars>>
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl PluginFor<Response> for HandlebarsEngine {
    type Error = ();

    fn eval(resp: &mut Response) -> Result<Template, ()> {
        match resp.extensions.get::<HandlebarsEngine>(){
            Some(t) => Ok(t.clone()),
            None => Err(())
        }
    }
}

impl HandlebarsEngine {
    /// #[Deprecated], for backward compaitibility only
    pub fn new(prefix: &str, suffix: &str) -> HandlebarsEngine {
        let mut hbs = HandlebarsEngine::new2();
        hbs.add(Box::new(DirectorySource::new(prefix, suffix)));
        hbs.reload();
        hbs
    }

    /// #[Deprecated], for backward compaitibility only
    pub fn from(prefix: &str, suffix: &str, custom: Handlebars) -> HandlebarsEngine {
        let mut hbs = HandlebarsEngine::from2(custom);
        hbs.add(Box::new(DirectorySource::new(prefix, suffix)));
        hbs.reload();
        hbs
    }

    pub fn new2() -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(Handlebars::new()))
        }
    }

    pub fn from2(reg: Handlebars) -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(reg))
        }
    }

    pub fn add(&mut self, source: Box<Source + Send + Sync>) {
        self.sources.push(source);
    }

    #[allow(unused_must_use)]
    pub fn reload(&self) -> Result<(), SourceError> {
        let mut hbs = self.registry.write().unwrap();
        hbs.clear_templates();
        for s in self.sources.iter() {
            try!(s.load(&mut hbs))
        }
        Ok(())
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, r: Response) -> IronResult<Response> {
        let mut resp = r;
        let page_wrapper = resp.extensions.get::<HandlebarsEngine>().as_ref()
            .and_then(|h| {
                let hbs = self.registry.read().unwrap();
                Some(hbs.render(&h.name, &h.value))
            });

        match page_wrapper {
            Some(page_result) => {
                match page_result {
                    Ok(page) => {
                        if !resp.headers.has::<ContentType>() {
                            resp.headers.set(ContentType::html());
                        }
                        resp.set_mut(page);
                        Ok(resp)
                    }
                    Err(e) => {
                        info!("{}", e.description());
                        Err(IronError::new(e, status::InternalServerError))
                    }
                }
            }
            None => {
                Ok(resp)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use serialize::json::ToJson;
    use std::collections::BTreeMap;
    use iron::prelude::*;
    use middleware::*;
    use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};

    fn hello_world() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_string(), "Handlebars on Iron".to_json());

        Ok(resp.set(Template::new("index", data)))
    }

    #[test]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name, "index".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new2();
        let mut reg = hbs.registry.write().unwrap();
        reg.register_helper("ignore", Box::new(|_: &Context, _: &Helper, _: &Handlebars, _: &mut RenderContext| -> Result<(), RenderError> {
            Ok(())
        }));
    }
}
<|endoftext|>


<commit_before>use either::Either;

use na::{Real, Cholesky, Dynamic, DVectorSliceMut, VectorSliceMutN, Point2, Point3, Point4, DVector, DVectorSlice};
use ncollide::shape::{Segment, Triangle};
use ncollide::query::PointQueryWithLocation;
#[cfg(feature = "dim3")]
use ncollide::shape::Tetrahedron;

use object::BodyStatus;
use solver::ForceDirection;
use math::{Point, Isometry, Dim, DIM};

/// Indices of the nodes of on element of a body decomposed in finite elements.
#[derive(Copy, Clone, Debug)]
pub enum FiniteElementIndices {
    #[cfg(feature = "dim3")]
    /// A tetrahedral element.
    Tetrahedron(Point4<usize>),
    /// A triangular element.
    Triangle(Point3<usize>),
    /// A segment element.
    Segment(Point2<usize>)
}

#[inline]
pub fn fill_contact_geometry_fem<N: Real>(
    ndofs: usize,
    status: BodyStatus,
    indices: FiniteElementIndices,
    positions: &DVector<N>,
    velocities: &DVector<N>,
    kinematic_nodes: &DVector<bool>,
    inv_augmented_mass: Either<N, &Cholesky<N, Dynamic>>,
    // Original parameters of fill_contact_geometry.
    center: &Point<N>,
    force_dir: &ForceDirection<N>,
    j_id: usize,
    wj_id: usize,
    jacobians: &mut [N],
    inv_r: &mut N,
    ext_vels: Option<&DVectorSlice<N>>,
    out_vel: Option<&mut N>
) {
    if status == BodyStatus::Static || status == BodyStatus::Disabled {
        return;
    }

    // Needed by the non-linear SOR-prox.
    // FIXME: should this `fill` be done by the non-linear SOR-prox itself?
    DVectorSliceMut::from_slice(&mut jacobians[j_id..], ndofs).fill(N::zero());

    if let ForceDirection::Linear(dir) = force_dir {
        match indices {
            FiniteElementIndices::Segment(indices) => {
                let kinematic1 = kinematic_nodes[indices.x / DIM];
                let kinematic2 = kinematic_nodes[indices.y / DIM];

                let a = positions.fixed_rows::<Dim>(indices.x).into_owned();
                let b = positions.fixed_rows::<Dim>(indices.y).into_owned();

                let seg = Segment::new(
                    Point::from_coordinates(a),
                    Point::from_coordinates(b),
                );

                // FIXME: This is costly!
                let proj = seg.project_point_with_location(&Isometry::identity(), center, false).1;
                let bcoords = proj.barycentric_coordinates();

                let dir1 = **dir * bcoords[0];
                let dir2 = **dir * bcoords[1];

                if status == BodyStatus::Dynamic {
                    if !kinematic1 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.x..]).copy_from(&dir1);
                    }
                    if !kinematic2 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.y..]).copy_from(&dir2);
                    }
                }

                if let Some(out_vel) = out_vel {
                    let va = velocities.fixed_rows::<Dim>(indices.x);
                    let vb = velocities.fixed_rows::<Dim>(indices.y);

                    *out_vel += va.dot(&dir1) + vb.dot(&dir2);

                    if let Some(ext_vels) = ext_vels {
                        if !kinematic1 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.x).dot(&dir1);
                        }
                        if !kinematic2 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.y).dot(&dir2);
                        }
                    }
                }
            }
            FiniteElementIndices::Triangle(indices) => {
                let kinematic1 = kinematic_nodes[indices.x / DIM];
                let kinematic2 = kinematic_nodes[indices.y / DIM];
                let kinematic3 = kinematic_nodes[indices.z / DIM];

                let a = positions.fixed_rows::<Dim>(indices.x).into_owned();
                let b = positions.fixed_rows::<Dim>(indices.y).into_owned();
                let c = positions.fixed_rows::<Dim>(indices.z).into_owned();

                let tri = Triangle::new(
                    Point::from_coordinates(a),
                    Point::from_coordinates(b),
                    Point::from_coordinates(c),
                );

                // FIXME: This is costly!
                let proj = tri.project_point_with_location(&Isometry::identity(), center, false).1;
                let bcoords = proj.barycentric_coordinates().unwrap();

                let dir1 = **dir * bcoords[0];
                let dir2 = **dir * bcoords[1];
                let dir3 = **dir * bcoords[2];

                if status == BodyStatus::Dynamic {
                    if !kinematic1 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.x..]).copy_from(&dir1);
                    }
                    if !kinematic2 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.y..]).copy_from(&dir2);
                    }
                    if !kinematic3 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.z..]).copy_from(&dir3);
                    }
                }

                if let Some(out_vel) = out_vel {
                    let va = velocities.fixed_rows::<Dim>(indices.x);
                    let vb = velocities.fixed_rows::<Dim>(indices.y);
                    let vc = velocities.fixed_rows::<Dim>(indices.z);

                    *out_vel += va.dot(&dir1) + vb.dot(&dir2) + vc.dot(&dir3);

                    if let Some(ext_vels) = ext_vels {
                        if !kinematic1 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.x).dot(&dir1);
                        }
                        if !kinematic2 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.y).dot(&dir2);
                        }
                        if !kinematic3 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.z).dot(&dir3);
                        }
                    }
                }
            }
            #[cfg(feature = "dim3")]
            FiniteElementIndices::Tetrahedron(indices) => {
                let kinematic1 = kinematic_nodes[indices.x / DIM];
                let kinematic2 = kinematic_nodes[indices.y / DIM];
                let kinematic3 = kinematic_nodes[indices.z / DIM];
                let kinematic4 = kinematic_nodes[indices.w / DIM];

                let a = positions.fixed_rows::<Dim>(indices.x).into_owned();
                let b = positions.fixed_rows::<Dim>(indices.y).into_owned();
                let c = positions.fixed_rows::<Dim>(indices.z).into_owned();
                let d = positions.fixed_rows::<Dim>(indices.w).into_owned();

                let tetra = Tetrahedron::new(
                    Point3::from_coordinates(a),
                    Point3::from_coordinates(b),
                    Point3::from_coordinates(c),
                    Point3::from_coordinates(d),
                );

                // XXX: This is extremely costly!
                let proj = tetra.project_point_with_location(&Isometry::identity(), center, true).1;

                let bcoords = if let Some(b) = proj.barycentric_coordinates() {
                    b
                } else {
                    unimplemented!()
//                    let pt_a = center.coords - a;
//                    // XXX: we have to update j_inv to use the new positions here!
//                    let b = elt.j_inv.tr_mul(&pt_a);
//                    [(N::one() - b.x - b.y - b.z), b.x, b.y, b.z]
                };

                let dir1 = **dir * bcoords[0];
                let dir2 = **dir * bcoords[1];
                let dir3 = **dir * bcoords[2];
                let dir4 = **dir * bcoords[3];

                if status == BodyStatus::Dynamic {
                    if !kinematic1 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.x..]).copy_from(&dir1);
                    }
                    if !kinematic2 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.y..]).copy_from(&dir2);
                    }
                    if !kinematic3 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.z..]).copy_from(&dir3);
                    }
                    if !kinematic4 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.w..]).copy_from(&dir4);
                    }
                }

                if let Some(out_vel) = out_vel {
                    let va = velocities.fixed_rows::<Dim>(indices.x);
                    let vb = velocities.fixed_rows::<Dim>(indices.y);
                    let vc = velocities.fixed_rows::<Dim>(indices.z);
                    let vd = velocities.fixed_rows::<Dim>(indices.w);

                    *out_vel += va.dot(&dir1) + vb.dot(&dir2) + vc.dot(&dir3) + vd.dot(&dir4);

                    if let Some(ext_vels) = ext_vels {
                        if !kinematic1 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.x).dot(&dir1);
                        }
                        if !kinematic2 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.y).dot(&dir2);
                        }
                        if !kinematic3 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.z).dot(&dir3);
                        }
                        if !kinematic4 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.w).dot(&dir4);
                        }
                    }
                }
            }
        }

        if status == BodyStatus::Dynamic {
            match inv_augmented_mass {
                Either::Right(inv_augmented_mass) => {
                    // FIXME: use a mem::copy_nonoverlapping?
                    for i in 0..ndofs {
                        jacobians[wj_id + i] = jacobians[j_id + i];
                    }

                    inv_augmented_mass.solve_mut(&mut DVectorSliceMut::from_slice(&mut jacobians[wj_id..], ndofs));
                },
                Either::Left(inv_augmented_mass) => {
                    for i in 0..ndofs {
                        jacobians[wj_id + i] = jacobians[j_id + i] * inv_augmented_mass;
                    }
                }
            }

            // FIXME: optimize this because j is sparse.
            *inv_r += DVectorSlice::from_slice(&jacobians[j_id..], ndofs).dot(&DVectorSlice::from_slice(&jacobians[wj_id..], ndofs));
        }
    }
}<commit_msg>Fix unreachable in fem_helper.<commit_after>use either::Either;

use na::{Real, Cholesky, Dynamic, DVectorSliceMut, VectorSliceMutN, Point2, Point3, Point4, DVector, DVectorSlice};
#[cfg(feature = "dim3")]
use na::Matrix3;
use ncollide::shape::{Segment, Triangle};
use ncollide::query::PointQueryWithLocation;
#[cfg(feature = "dim3")]
use ncollide::shape::Tetrahedron;

use object::BodyStatus;
use solver::ForceDirection;
use math::{Point, Isometry, Dim, DIM};

/// Indices of the nodes of on element of a body decomposed in finite elements.
#[derive(Copy, Clone, Debug)]
pub enum FiniteElementIndices {
    #[cfg(feature = "dim3")]
    /// A tetrahedral element.
    Tetrahedron(Point4<usize>),
    /// A triangular element.
    Triangle(Point3<usize>),
    /// A segment element.
    Segment(Point2<usize>)
}

#[inline]
pub fn fill_contact_geometry_fem<N: Real>(
    ndofs: usize,
    status: BodyStatus,
    indices: FiniteElementIndices,
    positions: &DVector<N>,
    velocities: &DVector<N>,
    kinematic_nodes: &DVector<bool>,
    inv_augmented_mass: Either<N, &Cholesky<N, Dynamic>>,
    // Original parameters of fill_contact_geometry.
    center: &Point<N>,
    force_dir: &ForceDirection<N>,
    j_id: usize,
    wj_id: usize,
    jacobians: &mut [N],
    inv_r: &mut N,
    ext_vels: Option<&DVectorSlice<N>>,
    out_vel: Option<&mut N>
) {
    if status == BodyStatus::Static || status == BodyStatus::Disabled {
        return;
    }

    // Needed by the non-linear SOR-prox.
    // FIXME: should this `fill` be done by the non-linear SOR-prox itself?
    DVectorSliceMut::from_slice(&mut jacobians[j_id..], ndofs).fill(N::zero());

    if let ForceDirection::Linear(dir) = force_dir {
        match indices {
            FiniteElementIndices::Segment(indices) => {
                let kinematic1 = kinematic_nodes[indices.x / DIM];
                let kinematic2 = kinematic_nodes[indices.y / DIM];

                let a = positions.fixed_rows::<Dim>(indices.x).into_owned();
                let b = positions.fixed_rows::<Dim>(indices.y).into_owned();

                let seg = Segment::new(
                    Point::from_coordinates(a),
                    Point::from_coordinates(b),
                );

                // FIXME: This is costly!
                let proj = seg.project_point_with_location(&Isometry::identity(), center, false).1;
                let bcoords = proj.barycentric_coordinates();

                let dir1 = **dir * bcoords[0];
                let dir2 = **dir * bcoords[1];

                if status == BodyStatus::Dynamic {
                    if !kinematic1 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.x..]).copy_from(&dir1);
                    }
                    if !kinematic2 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.y..]).copy_from(&dir2);
                    }
                }

                if let Some(out_vel) = out_vel {
                    let va = velocities.fixed_rows::<Dim>(indices.x);
                    let vb = velocities.fixed_rows::<Dim>(indices.y);

                    *out_vel += va.dot(&dir1) + vb.dot(&dir2);

                    if let Some(ext_vels) = ext_vels {
                        if !kinematic1 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.x).dot(&dir1);
                        }
                        if !kinematic2 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.y).dot(&dir2);
                        }
                    }
                }
            }
            FiniteElementIndices::Triangle(indices) => {
                let kinematic1 = kinematic_nodes[indices.x / DIM];
                let kinematic2 = kinematic_nodes[indices.y / DIM];
                let kinematic3 = kinematic_nodes[indices.z / DIM];

                let a = positions.fixed_rows::<Dim>(indices.x).into_owned();
                let b = positions.fixed_rows::<Dim>(indices.y).into_owned();
                let c = positions.fixed_rows::<Dim>(indices.z).into_owned();

                let tri = Triangle::new(
                    Point::from_coordinates(a),
                    Point::from_coordinates(b),
                    Point::from_coordinates(c),
                );

                // FIXME: This is costly!
                let proj = tri.project_point_with_location(&Isometry::identity(), center, false).1;
                let bcoords = proj.barycentric_coordinates().unwrap();

                let dir1 = **dir * bcoords[0];
                let dir2 = **dir * bcoords[1];
                let dir3 = **dir * bcoords[2];

                if status == BodyStatus::Dynamic {
                    if !kinematic1 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.x..]).copy_from(&dir1);
                    }
                    if !kinematic2 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.y..]).copy_from(&dir2);
                    }
                    if !kinematic3 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.z..]).copy_from(&dir3);
                    }
                }

                if let Some(out_vel) = out_vel {
                    let va = velocities.fixed_rows::<Dim>(indices.x);
                    let vb = velocities.fixed_rows::<Dim>(indices.y);
                    let vc = velocities.fixed_rows::<Dim>(indices.z);

                    *out_vel += va.dot(&dir1) + vb.dot(&dir2) + vc.dot(&dir3);

                    if let Some(ext_vels) = ext_vels {
                        if !kinematic1 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.x).dot(&dir1);
                        }
                        if !kinematic2 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.y).dot(&dir2);
                        }
                        if !kinematic3 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.z).dot(&dir3);
                        }
                    }
                }
            }
            #[cfg(feature = "dim3")]
            FiniteElementIndices::Tetrahedron(indices) => {
                let kinematic1 = kinematic_nodes[indices.x / DIM];
                let kinematic2 = kinematic_nodes[indices.y / DIM];
                let kinematic3 = kinematic_nodes[indices.z / DIM];
                let kinematic4 = kinematic_nodes[indices.w / DIM];

                let a = positions.fixed_rows::<Dim>(indices.x).into_owned();
                let b = positions.fixed_rows::<Dim>(indices.y).into_owned();
                let c = positions.fixed_rows::<Dim>(indices.z).into_owned();
                let d = positions.fixed_rows::<Dim>(indices.w).into_owned();

                let tetra = Tetrahedron::new(
                    Point3::from_coordinates(a),
                    Point3::from_coordinates(b),
                    Point3::from_coordinates(c),
                    Point3::from_coordinates(d),
                );

                // XXX: This is extremely costly!
                let proj = tetra.project_point_with_location(&Isometry::identity(), center, true).1;

                let bcoords = if let Some(b) = proj.barycentric_coordinates() {
                    b
                } else {
                    let pt_a = center.coords - a;
                    let mat = Matrix3::from_columns(&[b - a, c - a, d - a]);
                    let b = mat.try_inverse().unwrap_or_else(|| Matrix3::identity()) * pt_a;
                    [(N::one() - b.x - b.y - b.z), b.x, b.y, b.z]
                };

                let dir1 = **dir * bcoords[0];
                let dir2 = **dir * bcoords[1];
                let dir3 = **dir * bcoords[2];
                let dir4 = **dir * bcoords[3];

                if status == BodyStatus::Dynamic {
                    if !kinematic1 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.x..]).copy_from(&dir1);
                    }
                    if !kinematic2 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.y..]).copy_from(&dir2);
                    }
                    if !kinematic3 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.z..]).copy_from(&dir3);
                    }
                    if !kinematic4 {
                        VectorSliceMutN::<N, Dim>::from_slice(&mut jacobians[j_id + indices.w..]).copy_from(&dir4);
                    }
                }

                if let Some(out_vel) = out_vel {
                    let va = velocities.fixed_rows::<Dim>(indices.x);
                    let vb = velocities.fixed_rows::<Dim>(indices.y);
                    let vc = velocities.fixed_rows::<Dim>(indices.z);
                    let vd = velocities.fixed_rows::<Dim>(indices.w);

                    *out_vel += va.dot(&dir1) + vb.dot(&dir2) + vc.dot(&dir3) + vd.dot(&dir4);

                    if let Some(ext_vels) = ext_vels {
                        if !kinematic1 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.x).dot(&dir1);
                        }
                        if !kinematic2 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.y).dot(&dir2);
                        }
                        if !kinematic3 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.z).dot(&dir3);
                        }
                        if !kinematic4 {
                            *out_vel += ext_vels.fixed_rows::<Dim>(indices.w).dot(&dir4);
                        }
                    }
                }
            }
        }

        if status == BodyStatus::Dynamic {
            match inv_augmented_mass {
                Either::Right(inv_augmented_mass) => {
                    // FIXME: use a mem::copy_nonoverlapping?
                    for i in 0..ndofs {
                        jacobians[wj_id + i] = jacobians[j_id + i];
                    }

                    inv_augmented_mass.solve_mut(&mut DVectorSliceMut::from_slice(&mut jacobians[wj_id..], ndofs));
                },
                Either::Left(inv_augmented_mass) => {
                    for i in 0..ndofs {
                        jacobians[wj_id + i] = jacobians[j_id + i] * inv_augmented_mass;
                    }
                }
            }

            // FIXME: optimize this because j is sparse.
            *inv_r += DVectorSlice::from_slice(&jacobians[j_id..], ndofs).dot(&DVectorSlice::from_slice(&jacobians[wj_id..], ndofs));
        }
    }
}<|endoftext|>


<commit_before>use nom::{alpha};
use std::str;

fn bytes_vector_to_string(bytes: Vec<&[u8]>) -> String {
    // TODO: Fix this unwrap
    bytes
        .iter()
        .map(|b| bytes_to_string(b))
        .collect::<String>()
}

fn bytes_to_string(bytes: &[u8]) -> String {
    str::from_utf8(bytes).unwrap().to_string()
}

// In Lisp, we can use symbols for identifiers so parse them as such
named!(pub symbol_identifier<String>,
    map!(
        many0!(
            alt!(tag!("{")
                | tag!("}")
                | tag!("(")
                | tag!(")")
                | tag!("[")
                | tag!("]")
                | tag!(".")
                | tag!(";")
                | tag!(",")
                | tag!("<")
                | tag!(">")
                | tag!("=")
                | tag!("!")
                | tag!("+")
                | tag!("-")
                | tag!("*")
                | tag!("/")
                | tag!("&")
                | tag!("|")
                | tag!("^")
                | tag!("~")
                | tag!("?")
                | tag!(":")
            )
        ), bytes_vector_to_string
    )
);

// Represents letters etc in identifiers
named!(pub alpha_identifier<String>, map!(recognize!(alpha), bytes_to_string));<commit_msg>Perform lint and remove old function<commit_after>use nom::alpha;
use std::str;

fn bytes_to_string(bytes: &[u8]) -> String {
    str::from_utf8(bytes).unwrap().to_string()
}

// In Lisp, we can use symbols for identifiers so parse them as such
named!(pub symbol_identifier<String>,
    map!(
        recognize!(
            many0!(
                alt!(tag!("{")
                    | tag!("}")
                    | tag!("(")
                    | tag!(")")
                    | tag!("[")
                    | tag!("]")
                    | tag!(".")
                    | tag!(";")
                    | tag!(",")
                    | tag!("<")
                    | tag!(">")
                    | tag!("=")
                    | tag!("!")
                    | tag!("+")
                    | tag!("-")
                    | tag!("*")
                    | tag!("/")
                    | tag!("&")
                    | tag!("|")
                    | tag!("^")
                    | tag!("~")
                    | tag!("?")
                    | tag!(":")
                )
            )
        ), bytes_to_string
    )
);

// Represents letters etc in identifiers
named!(pub alpha_identifier<String>, map!(recognize!(alpha), bytes_to_string));
<|endoftext|>