<commit_before>//! The JIT driver uses [`cranelift_simplejit`] to JIT execute programs without writing any object
//! files.

use std::cell::RefCell;
use std::ffi::CString;
use std::os::raw::{c_char, c_int};

use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_codegen_ssa::CrateInfo;
use rustc_middle::mir::mono::MonoItem;
use rustc_session::config::EntryFnType;

use cranelift_jit::{JITBuilder, JITModule};

use crate::{prelude::*, BackendConfig};
use crate::{CodegenCx, CodegenMode};

thread_local! {
    pub static BACKEND_CONFIG: RefCell<Option<BackendConfig>> = RefCell::new(None);
    pub static CURRENT_MODULE: RefCell<Option<JITModule>> = RefCell::new(None);
}

pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
    if !tcx.sess.opts.output_types.should_codegen() {
        tcx.sess.fatal("JIT mode doesn't work with `cargo check`.");
    }

    let imported_symbols = load_imported_symbols_for_jit(tcx);

    let isa = crate::build_isa(tcx.sess, &backend_config);
    let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
    jit_builder.hotswap(matches!(backend_config.codegen_mode, CodegenMode::JitLazy));
    crate::compiler_builtins::register_functions_for_jit(&mut jit_builder);
    jit_builder.symbols(imported_symbols);
    let mut jit_module = JITModule::new(jit_builder);
    assert_eq!(pointer_ty(tcx), jit_module.target_config().pointer_type());

    let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
    let mono_items = cgus
        .iter()
        .map(|cgu| cgu.items_in_deterministic_order(tcx).into_iter())
        .flatten()
        .collect::<FxHashMap<_, (_, _)>>()
        .into_iter()
        .collect::<Vec<(_, (_, _))>>();

    let mut cx = crate::CodegenCx::new(tcx, backend_config.clone(), &mut jit_module, false);

    super::time(tcx, backend_config.display_cg_time, "codegen mono items", || {
        super::predefine_mono_items(&mut cx, &mono_items);
        for (mono_item, _) in mono_items {
            match mono_item {
                MonoItem::Fn(inst) => match backend_config.codegen_mode {
                    CodegenMode::Aot => unreachable!(),
                    CodegenMode::Jit => {
                        cx.tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, inst));
                    }
                    CodegenMode::JitLazy => codegen_shim(&mut cx, inst),
                },
                MonoItem::Static(def_id) => {
                    crate::constant::codegen_static(&mut cx, def_id);
                }
                MonoItem::GlobalAsm(item_id) => {
                    let item = cx.tcx.hir().item(item_id);
                    tcx.sess.span_fatal(item.span, "Global asm is not supported in JIT mode");
                }
            }
        }
    });

    let (global_asm, _debug, mut unwind_context) =
        tcx.sess.time("finalize CodegenCx", || cx.finalize());
    jit_module.finalize_definitions();

    if !global_asm.is_empty() {
        tcx.sess.fatal("Inline asm is not supported in JIT mode");
    }

    crate::allocator::codegen(tcx, &mut jit_module, &mut unwind_context);

    tcx.sess.abort_if_errors();

    jit_module.finalize_definitions();
    let _unwind_register_guard = unsafe { unwind_context.register_jit(&jit_module) };

    println!(
        "Rustc codegen cranelift will JIT run the executable, because -Cllvm-args=mode=jit was passed"
    );

    let args = std::iter::once(&*tcx.crate_name(LOCAL_CRATE).as_str().to_string())
        .chain(backend_config.jit_args.iter().map(|arg| &**arg))
        .map(|arg| CString::new(arg).unwrap())
        .collect::<Vec<_>>();
    let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();

    // Push a null pointer as a terminating argument. This is required by POSIX and
    // useful as some dynamic linkers use it as a marker to jump over.
    argv.push(std::ptr::null());

    BACKEND_CONFIG.with(|tls_backend_config| {
        assert!(tls_backend_config.borrow_mut().replace(backend_config).is_none())
    });

    let (main_def_id, entry_ty) = tcx.entry_fn(LOCAL_CRATE).unwrap();
    let instance = Instance::mono(tcx, main_def_id.to_def_id()).polymorphize(tcx);

    match entry_ty {
        EntryFnType::Main => {
            // FIXME set program arguments somehow

            let main_sig = Signature {
                params: vec![],
                returns: vec![],
                call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)),
            };
            let main_func_id = jit_module
                .declare_function(tcx.symbol_name(instance).name, Linkage::Import, &main_sig)
                .unwrap();
            let finalized_main: *const u8 = jit_module.get_finalized_function(main_func_id);

            CURRENT_MODULE.with(|current_module| {
                assert!(current_module.borrow_mut().replace(jit_module).is_none())
            });

            let f: extern "C" fn() = unsafe { ::std::mem::transmute(finalized_main) };
            f();
            std::process::exit(0);
        }
        EntryFnType::Start => {
            let start_sig = Signature {
                params: vec![
                    AbiParam::new(jit_module.target_config().pointer_type()),
                    AbiParam::new(jit_module.target_config().pointer_type()),
                ],
                returns: vec![AbiParam::new(
                    jit_module.target_config().pointer_type(), /*isize*/
                )],
                call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)),
            };
            let start_func_id = jit_module
                .declare_function(tcx.symbol_name(instance).name, Linkage::Import, &start_sig)
                .unwrap();
            let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id);

            CURRENT_MODULE.with(|current_module| {
                assert!(current_module.borrow_mut().replace(jit_module).is_none())
            });

            let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
                unsafe { ::std::mem::transmute(finalized_start) };
            let ret = f(args.len() as c_int, argv.as_ptr());
            std::process::exit(ret);
        }
    }
}

#[no_mangle]
extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8 {
    rustc_middle::ty::tls::with(|tcx| {
        // lift is used to ensure the correct lifetime for instance.
        let instance = tcx.lift(unsafe { *instance_ptr }).unwrap();

        CURRENT_MODULE.with(|jit_module| {
            let mut jit_module = jit_module.borrow_mut();
            let jit_module = jit_module.as_mut().unwrap();
            let backend_config =
                BACKEND_CONFIG.with(|backend_config| backend_config.borrow().clone().unwrap());

            let name = tcx.symbol_name(instance).name.to_string();
            let sig = crate::abi::get_function_sig(tcx, jit_module.isa().triple(), instance);
            let func_id = jit_module.declare_function(&name, Linkage::Export, &sig).unwrap();
            jit_module.prepare_for_function_redefine(func_id).unwrap();

            let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module, false);
            tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, instance));

            let (global_asm, _debug_context, unwind_context) = cx.finalize();
            assert!(global_asm.is_empty());
            jit_module.finalize_definitions();
            std::mem::forget(unsafe { unwind_context.register_jit(&jit_module) });
            jit_module.get_finalized_function(func_id)
        })
    })
}

fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
    use rustc_middle::middle::dependency_format::Linkage;

    let mut dylib_paths = Vec::new();

    let crate_info = CrateInfo::new(tcx);
    let formats = tcx.dependency_formats(LOCAL_CRATE);
    let data = &formats
        .iter()
        .find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable)
        .unwrap()
        .1;
    for &(cnum, _) in &crate_info.used_crates_dynamic {
        let src = &crate_info.used_crate_source[&cnum];
        match data[cnum.as_usize() - 1] {
            Linkage::NotLinked | Linkage::IncludedFromDylib => {}
            Linkage::Static => {
                let name = tcx.crate_name(cnum);
                let mut err =
                    tcx.sess.struct_err(&format!("Can't load static lib {}", name.as_str()));
                err.note("rustc_codegen_cranelift can only load dylibs in JIT mode.");
                err.emit();
            }
            Linkage::Dynamic => {
                dylib_paths.push(src.dylib.as_ref().unwrap().0.clone());
            }
        }
    }

    let mut imported_symbols = Vec::new();
    for path in dylib_paths {
        use object::{Object, ObjectSymbol};
        let lib = libloading::Library::new(&path).unwrap();
        let obj = std::fs::read(path).unwrap();
        let obj = object::File::parse(&obj).unwrap();
        imported_symbols.extend(obj.dynamic_symbols().filter_map(|symbol| {
            let name = symbol.name().unwrap().to_string();
            if name.is_empty() || !symbol.is_global() || symbol.is_undefined() {
                return None;
            }
            if name.starts_with("rust_metadata_") {
                // The metadata is part of a section that is not loaded by the dynamic linker in
                // case of cg_llvm.
                return None;
            }
            let dlsym_name = if cfg!(target_os = "macos") {
                // On macOS `dlsym` expects the name without leading `_`.
                assert!(name.starts_with('_'), "{:?}", name);
                &name[1..]
            } else {
                &name
            };
            let symbol: libloading::Symbol<'_, *const u8> =
                unsafe { lib.get(dlsym_name.as_bytes()) }.unwrap();
            Some((name, *symbol))
        }));
        std::mem::forget(lib)
    }

    tcx.sess.abort_if_errors();

    imported_symbols
}

fn codegen_shim<'tcx>(cx: &mut CodegenCx<'_, 'tcx>, inst: Instance<'tcx>) {
    let tcx = cx.tcx;

    let pointer_type = cx.module.target_config().pointer_type();

    let name = tcx.symbol_name(inst).name.to_string();
    let sig = crate::abi::get_function_sig(tcx, cx.module.isa().triple(), inst);
    let func_id = cx.module.declare_function(&name, Linkage::Export, &sig).unwrap();

    let instance_ptr = Box::into_raw(Box::new(inst));

    let jit_fn = cx
        .module
        .declare_function(
            "__clif_jit_fn",
            Linkage::Import,
            &Signature {
                call_conv: cx.module.target_config().default_call_conv,
                params: vec![AbiParam::new(pointer_type)],
                returns: vec![AbiParam::new(pointer_type)],
            },
        )
        .unwrap();

    let mut trampoline = Function::with_name_signature(ExternalName::default(), sig.clone());
    let mut builder_ctx = FunctionBuilderContext::new();
    let mut trampoline_builder = FunctionBuilder::new(&mut trampoline, &mut builder_ctx);

    let jit_fn = cx.module.declare_func_in_func(jit_fn, trampoline_builder.func);
    let sig_ref = trampoline_builder.func.import_signature(sig);

    let entry_block = trampoline_builder.create_block();
    trampoline_builder.append_block_params_for_function_params(entry_block);
    let fn_args = trampoline_builder.func.dfg.block_params(entry_block).to_vec();

    trampoline_builder.switch_to_block(entry_block);
    let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64);
    let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr]);
    let jitted_fn = trampoline_builder.func.dfg.inst_results(jitted_fn)[0];
    let call_inst = trampoline_builder.ins().call_indirect(sig_ref, jitted_fn, &fn_args);
    let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec();
    trampoline_builder.ins().return_(&ret_vals);

    cx.module
        .define_function(
            func_id,
            &mut Context::for_function(trampoline),
            &mut NullTrapSink {},
            &mut NullStackMapSink {},
        )
        .unwrap();
}
<commit_msg>Re-use Context in codegen_shim<commit_after>//! The JIT driver uses [`cranelift_simplejit`] to JIT execute programs without writing any object
//! files.

use std::cell::RefCell;
use std::ffi::CString;
use std::os::raw::{c_char, c_int};

use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_codegen_ssa::CrateInfo;
use rustc_middle::mir::mono::MonoItem;
use rustc_session::config::EntryFnType;

use cranelift_jit::{JITBuilder, JITModule};

use crate::{prelude::*, BackendConfig};
use crate::{CodegenCx, CodegenMode};

thread_local! {
    pub static BACKEND_CONFIG: RefCell<Option<BackendConfig>> = RefCell::new(None);
    pub static CURRENT_MODULE: RefCell<Option<JITModule>> = RefCell::new(None);
}

pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
    if !tcx.sess.opts.output_types.should_codegen() {
        tcx.sess.fatal("JIT mode doesn't work with `cargo check`.");
    }

    let imported_symbols = load_imported_symbols_for_jit(tcx);

    let isa = crate::build_isa(tcx.sess, &backend_config);
    let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
    jit_builder.hotswap(matches!(backend_config.codegen_mode, CodegenMode::JitLazy));
    crate::compiler_builtins::register_functions_for_jit(&mut jit_builder);
    jit_builder.symbols(imported_symbols);
    let mut jit_module = JITModule::new(jit_builder);
    assert_eq!(pointer_ty(tcx), jit_module.target_config().pointer_type());

    let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
    let mono_items = cgus
        .iter()
        .map(|cgu| cgu.items_in_deterministic_order(tcx).into_iter())
        .flatten()
        .collect::<FxHashMap<_, (_, _)>>()
        .into_iter()
        .collect::<Vec<(_, (_, _))>>();

    let mut cx = crate::CodegenCx::new(tcx, backend_config.clone(), &mut jit_module, false);

    super::time(tcx, backend_config.display_cg_time, "codegen mono items", || {
        super::predefine_mono_items(&mut cx, &mono_items);
        for (mono_item, _) in mono_items {
            match mono_item {
                MonoItem::Fn(inst) => match backend_config.codegen_mode {
                    CodegenMode::Aot => unreachable!(),
                    CodegenMode::Jit => {
                        cx.tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, inst));
                    }
                    CodegenMode::JitLazy => codegen_shim(&mut cx, inst),
                },
                MonoItem::Static(def_id) => {
                    crate::constant::codegen_static(&mut cx, def_id);
                }
                MonoItem::GlobalAsm(item_id) => {
                    let item = cx.tcx.hir().item(item_id);
                    tcx.sess.span_fatal(item.span, "Global asm is not supported in JIT mode");
                }
            }
        }
    });

    let (global_asm, _debug, mut unwind_context) =
        tcx.sess.time("finalize CodegenCx", || cx.finalize());
    jit_module.finalize_definitions();

    if !global_asm.is_empty() {
        tcx.sess.fatal("Inline asm is not supported in JIT mode");
    }

    crate::allocator::codegen(tcx, &mut jit_module, &mut unwind_context);

    tcx.sess.abort_if_errors();

    jit_module.finalize_definitions();
    let _unwind_register_guard = unsafe { unwind_context.register_jit(&jit_module) };

    println!(
        "Rustc codegen cranelift will JIT run the executable, because -Cllvm-args=mode=jit was passed"
    );

    let args = std::iter::once(&*tcx.crate_name(LOCAL_CRATE).as_str().to_string())
        .chain(backend_config.jit_args.iter().map(|arg| &**arg))
        .map(|arg| CString::new(arg).unwrap())
        .collect::<Vec<_>>();
    let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();

    // Push a null pointer as a terminating argument. This is required by POSIX and
    // useful as some dynamic linkers use it as a marker to jump over.
    argv.push(std::ptr::null());

    BACKEND_CONFIG.with(|tls_backend_config| {
        assert!(tls_backend_config.borrow_mut().replace(backend_config).is_none())
    });

    let (main_def_id, entry_ty) = tcx.entry_fn(LOCAL_CRATE).unwrap();
    let instance = Instance::mono(tcx, main_def_id.to_def_id()).polymorphize(tcx);

    match entry_ty {
        EntryFnType::Main => {
            // FIXME set program arguments somehow

            let main_sig = Signature {
                params: vec![],
                returns: vec![],
                call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)),
            };
            let main_func_id = jit_module
                .declare_function(tcx.symbol_name(instance).name, Linkage::Import, &main_sig)
                .unwrap();
            let finalized_main: *const u8 = jit_module.get_finalized_function(main_func_id);

            CURRENT_MODULE.with(|current_module| {
                assert!(current_module.borrow_mut().replace(jit_module).is_none())
            });

            let f: extern "C" fn() = unsafe { ::std::mem::transmute(finalized_main) };
            f();
            std::process::exit(0);
        }
        EntryFnType::Start => {
            let start_sig = Signature {
                params: vec![
                    AbiParam::new(jit_module.target_config().pointer_type()),
                    AbiParam::new(jit_module.target_config().pointer_type()),
                ],
                returns: vec![AbiParam::new(
                    jit_module.target_config().pointer_type(), /*isize*/
                )],
                call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)),
            };
            let start_func_id = jit_module
                .declare_function(tcx.symbol_name(instance).name, Linkage::Import, &start_sig)
                .unwrap();
            let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id);

            CURRENT_MODULE.with(|current_module| {
                assert!(current_module.borrow_mut().replace(jit_module).is_none())
            });

            let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
                unsafe { ::std::mem::transmute(finalized_start) };
            let ret = f(args.len() as c_int, argv.as_ptr());
            std::process::exit(ret);
        }
    }
}

#[no_mangle]
extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8 {
    rustc_middle::ty::tls::with(|tcx| {
        // lift is used to ensure the correct lifetime for instance.
        let instance = tcx.lift(unsafe { *instance_ptr }).unwrap();

        CURRENT_MODULE.with(|jit_module| {
            let mut jit_module = jit_module.borrow_mut();
            let jit_module = jit_module.as_mut().unwrap();
            let backend_config =
                BACKEND_CONFIG.with(|backend_config| backend_config.borrow().clone().unwrap());

            let name = tcx.symbol_name(instance).name.to_string();
            let sig = crate::abi::get_function_sig(tcx, jit_module.isa().triple(), instance);
            let func_id = jit_module.declare_function(&name, Linkage::Export, &sig).unwrap();
            jit_module.prepare_for_function_redefine(func_id).unwrap();

            let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module, false);
            tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, instance));

            let (global_asm, _debug_context, unwind_context) = cx.finalize();
            assert!(global_asm.is_empty());
            jit_module.finalize_definitions();
            std::mem::forget(unsafe { unwind_context.register_jit(&jit_module) });
            jit_module.get_finalized_function(func_id)
        })
    })
}

fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
    use rustc_middle::middle::dependency_format::Linkage;

    let mut dylib_paths = Vec::new();

    let crate_info = CrateInfo::new(tcx);
    let formats = tcx.dependency_formats(LOCAL_CRATE);
    let data = &formats
        .iter()
        .find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable)
        .unwrap()
        .1;
    for &(cnum, _) in &crate_info.used_crates_dynamic {
        let src = &crate_info.used_crate_source[&cnum];
        match data[cnum.as_usize() - 1] {
            Linkage::NotLinked | Linkage::IncludedFromDylib => {}
            Linkage::Static => {
                let name = tcx.crate_name(cnum);
                let mut err =
                    tcx.sess.struct_err(&format!("Can't load static lib {}", name.as_str()));
                err.note("rustc_codegen_cranelift can only load dylibs in JIT mode.");
                err.emit();
            }
            Linkage::Dynamic => {
                dylib_paths.push(src.dylib.as_ref().unwrap().0.clone());
            }
        }
    }

    let mut imported_symbols = Vec::new();
    for path in dylib_paths {
        use object::{Object, ObjectSymbol};
        let lib = libloading::Library::new(&path).unwrap();
        let obj = std::fs::read(path).unwrap();
        let obj = object::File::parse(&obj).unwrap();
        imported_symbols.extend(obj.dynamic_symbols().filter_map(|symbol| {
            let name = symbol.name().unwrap().to_string();
            if name.is_empty() || !symbol.is_global() || symbol.is_undefined() {
                return None;
            }
            if name.starts_with("rust_metadata_") {
                // The metadata is part of a section that is not loaded by the dynamic linker in
                // case of cg_llvm.
                return None;
            }
            let dlsym_name = if cfg!(target_os = "macos") {
                // On macOS `dlsym` expects the name without leading `_`.
                assert!(name.starts_with('_'), "{:?}", name);
                &name[1..]
            } else {
                &name
            };
            let symbol: libloading::Symbol<'_, *const u8> =
                unsafe { lib.get(dlsym_name.as_bytes()) }.unwrap();
            Some((name, *symbol))
        }));
        std::mem::forget(lib)
    }

    tcx.sess.abort_if_errors();

    imported_symbols
}

fn codegen_shim<'tcx>(cx: &mut CodegenCx<'_, 'tcx>, inst: Instance<'tcx>) {
    let tcx = cx.tcx;

    let pointer_type = cx.module.target_config().pointer_type();

    let name = tcx.symbol_name(inst).name.to_string();
    let sig = crate::abi::get_function_sig(tcx, cx.module.isa().triple(), inst);
    let func_id = cx.module.declare_function(&name, Linkage::Export, &sig).unwrap();

    let instance_ptr = Box::into_raw(Box::new(inst));

    let jit_fn = cx
        .module
        .declare_function(
            "__clif_jit_fn",
            Linkage::Import,
            &Signature {
                call_conv: cx.module.target_config().default_call_conv,
                params: vec![AbiParam::new(pointer_type)],
                returns: vec![AbiParam::new(pointer_type)],
            },
        )
        .unwrap();

    cx.cached_context.clear();
    let trampoline = &mut cx.cached_context.func;
    trampoline.signature = sig.clone();

    let mut builder_ctx = FunctionBuilderContext::new();
    let mut trampoline_builder = FunctionBuilder::new(trampoline, &mut builder_ctx);

    let jit_fn = cx.module.declare_func_in_func(jit_fn, trampoline_builder.func);
    let sig_ref = trampoline_builder.func.import_signature(sig);

    let entry_block = trampoline_builder.create_block();
    trampoline_builder.append_block_params_for_function_params(entry_block);
    let fn_args = trampoline_builder.func.dfg.block_params(entry_block).to_vec();

    trampoline_builder.switch_to_block(entry_block);
    let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64);
    let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr]);
    let jitted_fn = trampoline_builder.func.dfg.inst_results(jitted_fn)[0];
    let call_inst = trampoline_builder.ins().call_indirect(sig_ref, jitted_fn, &fn_args);
    let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec();
    trampoline_builder.ins().return_(&ret_vals);

    cx.module
        .define_function(
            func_id,
            &mut cx.cached_context,
            &mut NullTrapSink {},
            &mut NullStackMapSink {},
        )
        .unwrap();
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 Johannes Köster, Peer Aramillo Irizar.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of alphabets and useful utilities.
//!
//! # Example
//!
//! ```rust
//! use bio::alphabets;
//! let alphabet = alphabets::dna::alphabet();
//! assert!(alphabet.is_word(b"AACCTgga"));
//! assert!(!alphabet.is_word(b"AXYZ"));
//! ```

use std::iter::FromIterator;
use std::slice;
use std::mem;

use bit_set::BitSet;
use vec_map::VecMap;

pub mod dna;
pub mod protein;

pub type SymbolRanks = VecMap<u8>;

/// Representation of an alphabet.
pub struct Alphabet {
    pub symbols: BitSet
}

impl Alphabet {
    /// Create new alphabet from given symbols.
    pub fn new(symbols: &[u8]) -> Self {
        Alphabet::from_iter(symbols.iter())
    }

    /// Insert symbol into alphabet.
    pub fn insert(&mut self, a: u8) {
        self.symbols.insert(a as usize);
    }

    /// Check if given text is a word over the alphabet.
    pub fn is_word(&self, text: &[u8]) -> bool {
        text.iter().all(|&c| self.symbols.contains(&(c as usize)))
    }

    /// Return lexicographically maximal symbol.
    pub fn max_symbol(&self) -> Option<u8> {
        self.symbols.iter().max().map(|a| a as u8)
    }

    /// Return size of the alphabet.
    pub fn len(&self) -> usize {
        self.symbols.len()
    }

    /// Is this alphabet empty?
    pub fn is_empty(&self) -> bool {
        self.symbols.is_empty()
    }
}

impl<'a> FromIterator<&'a u8> for Alphabet {
    /// Create a new alphabet from the given iterator.
    fn from_iter<T: IntoIterator<Item=&'a u8>>(iterator: T) -> Self {
        let mut s = BitSet::new();
        s.extend(iterator.into_iter().map(|&c| c as usize));

        Alphabet { symbols: s }
    }
}

/// Tools based on transforming the alphabet symbols to their lexicographical ranks.
pub struct RankTransform {
    pub ranks: SymbolRanks
}

impl RankTransform {
    /// Construct a new `RankTransform`.
    pub fn new(alphabet: &Alphabet) -> Self {
        let mut ranks = VecMap::new();
        for (r, c) in alphabet.symbols.iter().enumerate() {
            ranks.insert(c, r as u8);
        }

        RankTransform { ranks: ranks }
    }

    /// Get the rank of symbol `a`.
    pub fn get(&self, a: u8) -> u8 {
        *self.ranks.get(&(a as usize)).expect("Unexpected character.")
    }

    /// Transform a given `text`.
    pub fn transform(&self, text: &[u8]) -> Vec<u8> {
        text.iter()
            .map(|&c| *self.ranks.get(&(c as usize)).expect("Unexpected character in text."))
            .collect()
    }

    /// Iterate over q-grams (substrings of length q) of given `text`. The q-grams are encoded
    /// as `usize` by storing the symbol ranks in log2(|A|) bits (with |A| being the alphabet size).
    ///
    /// If q is larger than usize::BITS / log2(|A|), this method fails with an assertion.
    pub fn qgrams<'a>(&'a self, q: u32, text: &'a [u8]) -> QGrams {
        let bits = (self.ranks.len() as f32).log2().ceil() as u32;
        assert!((bits * q) as usize <= mem::size_of::<usize>() * 8, "Expecting q to be smaller than usize / log2(|A|)");

        let mut qgrams = QGrams {
            text: text.iter(),
            ranks: self,
            bits: bits,
            mask: (1 << (q * bits)) - 1,
            qgram: 0,
        };

        for _ in 0..q-1 {
            qgrams.next();
        }

        qgrams
    }

    /// Restore alphabet from transform.
    pub fn alphabet<'a>(&self) -> Alphabet {
        let mut symbols = BitSet::with_capacity(self.ranks.len());
        symbols.extend(self.ranks.keys());
        Alphabet { symbols: symbols }
    }
}

/// Iterator over q-grams.
pub struct QGrams<'a> {
    text: slice::Iter<'a, u8>,
    ranks: &'a RankTransform,
    bits: u32,
    mask: usize,
    qgram: usize,
}

impl<'a> QGrams<'a> {
    fn qgram_push(&mut self, a: u8) {
        self.qgram <<= self.bits;
        self.qgram |= a as usize;
        self.qgram &= self.mask;
    }
}

impl<'a> Iterator for QGrams<'a> {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        match self.text.next() {
            Some(a) => {
                let b = self.ranks.get(*a);
                self.qgram_push(b);
                Some(self.qgram)
            },
            None    => None
        }
    }
}
<commit_msg>Adapt to new bit-set version.<commit_after>// Copyright 2014-2015 Johannes Köster, Peer Aramillo Irizar.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of alphabets and useful utilities.
//!
//! # Example
//!
//! ```rust
//! use bio::alphabets;
//! let alphabet = alphabets::dna::alphabet();
//! assert!(alphabet.is_word(b"AACCTgga"));
//! assert!(!alphabet.is_word(b"AXYZ"));
//! ```

use std::iter::FromIterator;
use std::slice;
use std::mem;

use bit_set::BitSet;
use vec_map::VecMap;

pub mod dna;
pub mod protein;

pub type SymbolRanks = VecMap<u8>;

/// Representation of an alphabet.
pub struct Alphabet {
    pub symbols: BitSet
}

impl Alphabet {
    /// Create new alphabet from given symbols.
    pub fn new(symbols: &[u8]) -> Self {
        Alphabet::from_iter(symbols.iter())
    }

    /// Insert symbol into alphabet.
    pub fn insert(&mut self, a: u8) {
        self.symbols.insert(a as usize);
    }

    /// Check if given text is a word over the alphabet.
    pub fn is_word(&self, text: &[u8]) -> bool {
        text.iter().all(|&c| self.symbols.contains(c as usize))
    }

    /// Return lexicographically maximal symbol.
    pub fn max_symbol(&self) -> Option<u8> {
        self.symbols.iter().max().map(|a| a as u8)
    }

    /// Return size of the alphabet.
    pub fn len(&self) -> usize {
        self.symbols.len()
    }

    /// Is this alphabet empty?
    pub fn is_empty(&self) -> bool {
        self.symbols.is_empty()
    }
}

impl<'a> FromIterator<&'a u8> for Alphabet {
    /// Create a new alphabet from the given iterator.
    fn from_iter<T: IntoIterator<Item=&'a u8>>(iterator: T) -> Self {
        let mut s = BitSet::new();
        s.extend(iterator.into_iter().map(|&c| c as usize));

        Alphabet { symbols: s }
    }
}

/// Tools based on transforming the alphabet symbols to their lexicographical ranks.
pub struct RankTransform {
    pub ranks: SymbolRanks
}

impl RankTransform {
    /// Construct a new `RankTransform`.
    pub fn new(alphabet: &Alphabet) -> Self {
        let mut ranks = VecMap::new();
        for (r, c) in alphabet.symbols.iter().enumerate() {
            ranks.insert(c, r as u8);
        }

        RankTransform { ranks: ranks }
    }

    /// Get the rank of symbol `a`.
    pub fn get(&self, a: u8) -> u8 {
        *self.ranks.get(&(a as usize)).expect("Unexpected character.")
    }

    /// Transform a given `text`.
    pub fn transform(&self, text: &[u8]) -> Vec<u8> {
        text.iter()
            .map(|&c| *self.ranks.get(&(c as usize)).expect("Unexpected character in text."))
            .collect()
    }

    /// Iterate over q-grams (substrings of length q) of given `text`. The q-grams are encoded
    /// as `usize` by storing the symbol ranks in log2(|A|) bits (with |A| being the alphabet size).
    ///
    /// If q is larger than usize::BITS / log2(|A|), this method fails with an assertion.
    pub fn qgrams<'a>(&'a self, q: u32, text: &'a [u8]) -> QGrams {
        let bits = (self.ranks.len() as f32).log2().ceil() as u32;
        assert!((bits * q) as usize <= mem::size_of::<usize>() * 8, "Expecting q to be smaller than usize / log2(|A|)");

        let mut qgrams = QGrams {
            text: text.iter(),
            ranks: self,
            bits: bits,
            mask: (1 << (q * bits)) - 1,
            qgram: 0,
        };

        for _ in 0..q-1 {
            qgrams.next();
        }

        qgrams
    }

    /// Restore alphabet from transform.
    pub fn alphabet<'a>(&self) -> Alphabet {
        let mut symbols = BitSet::with_capacity(self.ranks.len());
        symbols.extend(self.ranks.keys());
        Alphabet { symbols: symbols }
    }
}

/// Iterator over q-grams.
pub struct QGrams<'a> {
    text: slice::Iter<'a, u8>,
    ranks: &'a RankTransform,
    bits: u32,
    mask: usize,
    qgram: usize,
}

impl<'a> QGrams<'a> {
    fn qgram_push(&mut self, a: u8) {
        self.qgram <<= self.bits;
        self.qgram |= a as usize;
        self.qgram &= self.mask;
    }
}

impl<'a> Iterator for QGrams<'a> {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        match self.text.next() {
            Some(a) => {
                let b = self.ranks.get(*a);
                self.qgram_push(b);
                Some(self.qgram)
            },
            None    => None
        }
    }
}
<|endoftext|>


<commit_before>use super::Backend;
use std::fs::{self, File};
use std::io;
use std::path::{Path, PathBuf};
use std::ffi::OsString;

/// Backend operating on the local filesystem.
pub struct LocalBackend {
    base_path: PathBuf,
}

/// Iterator over a set of file names.
pub struct FileNameIterator(fs::ReadDir);

impl LocalBackend {
    /// Create a new LocalBackend that operates on the given directory.
    pub fn new<P: AsRef<Path>>(path: P) -> Self {
        LocalBackend { base_path: path.as_ref().to_path_buf() }
    }
}

impl Backend for LocalBackend {
    type FileName = OsString;
    type FileNameIter = FileNameIterator;
    type FileStream = File;

    fn get_file_names(&self) -> io::Result<Self::FileNameIter> {
        let dir = try!(fs::read_dir(self.base_path.as_path()));
        Ok(FileNameIterator(dir))
    }

    fn open_file(&self, name: &Path) -> io::Result<File> {
        let mut path = self.base_path.clone();
        path.push(name);
        File::open(path)
    }
}

impl Iterator for FileNameIterator {
    type Item = OsString;

    fn next(&mut self) -> Option<OsString> {
        while let Some(entry) = self.0.next() {
            if let Ok(entry) = entry {
                return Some(entry.file_name());
            }
        }
        None
    }
}
<commit_msg>Fixed clippy lint warning<commit_after>use super::Backend;
use std::fs::{self, File};
use std::io;
use std::path::{Path, PathBuf};
use std::ffi::OsString;

/// Backend operating on the local filesystem.
pub struct LocalBackend {
    base_path: PathBuf,
}

/// Iterator over a set of file names.
pub struct FileNameIterator(fs::ReadDir);

impl LocalBackend {
    /// Create a new LocalBackend that operates on the given directory.
    pub fn new<P: AsRef<Path>>(path: P) -> Self {
        LocalBackend { base_path: path.as_ref().to_path_buf() }
    }
}

impl Backend for LocalBackend {
    type FileName = OsString;
    type FileNameIter = FileNameIterator;
    type FileStream = File;

    fn get_file_names(&self) -> io::Result<Self::FileNameIter> {
        let dir = try!(fs::read_dir(self.base_path.as_path()));
        Ok(FileNameIterator(dir))
    }

    fn open_file(&self, name: &Path) -> io::Result<File> {
        let mut path = self.base_path.clone();
        path.push(name);
        File::open(path)
    }
}

impl Iterator for FileNameIterator {
    type Item = OsString;

    fn next(&mut self) -> Option<OsString> {
        for entry in &mut self.0 {
            if let Ok(entry) = entry {
                return Some(entry.file_name());
            }
        }
        None
    }
}
<|endoftext|>


<commit_before>/**
 * A deque, for fun.  Untested as of yet.  Likely buggy.
 */

import std.util;
import std._vec;
import std._int;

type t[T] = obj {
  fn size() -> uint;

  fn add_front(&T t);
  fn add_back(&T t);

  fn pop_front() -> T;
  fn pop_back() -> T;

  fn peek_front() -> T;
  fn peek_back() -> T;

  fn get(int i) -> T;
};

fn create[T]() -> t[T] {

  type cell[T] = mutable util.option[T];

  let uint initial_capacity = 32u; // 2^5

  /**
   * Grow is only called on full elts, so nelts is also len(elts), unlike
   * elsewhere.
   */
  fn grow[T](uint nelts, uint lo, vec[cell[T]] elts) -> vec[cell[T]] {
    check (nelts == _vec.len[cell[T]](elts));

    fn fill[T](uint i, uint nelts, uint lo, &vec[cell[T]] old) -> cell[T] {
      if (i < nelts) {
        ret old.((lo + i) % nelts);
      } else {
        ret util.none[T]();
      }
    }

    let uint nalloc = _int.next_power_of_two(nelts + 1u);
    let _vec.init_op[cell[T]] copy_op = bind fill[T](_, nelts, lo, elts);
    ret _vec.init_fn[cell[T]](copy_op, nalloc);
  }

  fn get[T](&vec[cell[T]] elts, uint i) -> T {
    alt (elts.(i)) {
      case (util.some[T](t)) { ret t; }
      case (_) { fail; }
    }
  }

  obj deque[T](mutable uint nelts,
               mutable uint lo,
               mutable uint hi,
               mutable vec[cell[T]] elts)
  {
    fn size() -> uint { ret nelts; }

    fn add_front(&T t) {
      let uint oldlo = lo;

      if (lo == 0u) {
        lo = _vec.len[cell[T]](elts) - 1u;
      } else {
        lo -= 1u;
      }

      if (lo == hi) {
        elts = grow[T](nelts, oldlo, elts);
        lo = _vec.len[cell[T]](elts) - 1u;
        hi = nelts;
      }

      elts.(lo) = util.some[T](t);
      nelts += 1u;
    }

    fn add_back(&T t) {
      if (lo == hi && nelts != 0u) {
        elts = grow[T](nelts, lo, elts);
        lo = 0u;
        hi = nelts;
      }

      elts.(hi) = util.some[T](t);
      hi = (hi + 1u) % _vec.len[cell[T]](elts);
      nelts += 1u;
    }

    /**
     * We actually release (turn to none()) the T we're popping so that we
     * don't keep anyone's refcount up unexpectedly.
     */
    fn pop_front() -> T {
      let T t = get[T](elts, lo);
      elts.(lo) = util.none[T]();
      lo = (lo + 1u) % _vec.len[cell[T]](elts);
      ret t;
    }

    fn pop_back() -> T {
      if (hi == 0u) {
        hi = _vec.len[cell[T]](elts) - 1u;
      } else {
        hi -= 1u;
      }

      let T t = get[T](elts, hi);
      elts.(hi) = util.none[T]();
      ret t;
    }

    fn peek_front() -> T {
      ret get[T](elts, lo);
    }

    fn peek_back() -> T {
      ret get[T](elts, hi - 1u);
    }

    fn get(int i) -> T {
      let uint idx = (lo + (i as uint)) % _vec.len[cell[T]](elts);
      ret get[T](elts, idx);
    }
  }

  let vec[cell[T]] v = _vec.init_elt[cell[T]](util.none[T](),
                                              initial_capacity);

  ret deque[T](0u, 0u, 0u, v);
}
<commit_msg>Fix a deque size bookkeeping bug.<commit_after>/**
 * A deque, for fun.  Untested as of yet.  Likely buggy.
 */

import std.util;
import std._vec;
import std._int;

type t[T] = obj {
  fn size() -> uint;

  fn add_front(&T t);
  fn add_back(&T t);

  fn pop_front() -> T;
  fn pop_back() -> T;

  fn peek_front() -> T;
  fn peek_back() -> T;

  fn get(int i) -> T;
};

fn create[T]() -> t[T] {

  type cell[T] = mutable util.option[T];

  let uint initial_capacity = 32u; // 2^5

  /**
   * Grow is only called on full elts, so nelts is also len(elts), unlike
   * elsewhere.
   */
  fn grow[T](uint nelts, uint lo, vec[cell[T]] elts) -> vec[cell[T]] {
    check (nelts == _vec.len[cell[T]](elts));

    fn fill[T](uint i, uint nelts, uint lo, &vec[cell[T]] old) -> cell[T] {
      if (i < nelts) {
        ret old.((lo + i) % nelts);
      } else {
        ret util.none[T]();
      }
    }

    let uint nalloc = _int.next_power_of_two(nelts + 1u);
    let _vec.init_op[cell[T]] copy_op = bind fill[T](_, nelts, lo, elts);
    ret _vec.init_fn[cell[T]](copy_op, nalloc);
  }

  fn get[T](vec[cell[T]] elts, uint i) -> T {
    alt (elts.(i)) {
      case (util.some[T](t)) { ret t; }
      case (_) { fail; }
    }
  }

  obj deque[T](mutable uint nelts,
               mutable uint lo,
               mutable uint hi,
               mutable vec[cell[T]] elts)
  {
    fn size() -> uint { ret nelts; }

    fn add_front(&T t) {
      let uint oldlo = lo;

      if (lo == 0u) {
        lo = _vec.len[cell[T]](elts) - 1u;
      } else {
        lo -= 1u;
      }

      if (lo == hi) {
        elts = grow[T](nelts, oldlo, elts);
        lo = _vec.len[cell[T]](elts) - 1u;
        hi = nelts;
      }

      elts.(lo) = util.some[T](t);
      nelts += 1u;
    }

    fn add_back(&T t) {
      if (lo == hi && nelts != 0u) {
        elts = grow[T](nelts, lo, elts);
        lo = 0u;
        hi = nelts;
      }

      elts.(hi) = util.some[T](t);
      hi = (hi + 1u) % _vec.len[cell[T]](elts);
      nelts += 1u;
    }

    /**
     * We actually release (turn to none()) the T we're popping so that we
     * don't keep anyone's refcount up unexpectedly.
     */
    fn pop_front() -> T {
      let T t = get[T](elts, lo);
      elts.(lo) = util.none[T]();
      lo = (lo + 1u) % _vec.len[cell[T]](elts);
      nelts -= 1u;
      ret t;
    }

    fn pop_back() -> T {
      if (hi == 0u) {
        hi = _vec.len[cell[T]](elts) - 1u;
      } else {
        hi -= 1u;
      }

      let T t = get[T](elts, hi);
      elts.(hi) = util.none[T]();
      nelts -= 1u;
      ret t;
    }

    fn peek_front() -> T {
      ret get[T](elts, lo);
    }

    fn peek_back() -> T {
      ret get[T](elts, hi - 1u);
    }

    fn get(int i) -> T {
      let uint idx = (lo + (i as uint)) % _vec.len[cell[T]](elts);
      ret get[T](elts, idx);
    }
  }

  let vec[cell[T]] v = _vec.init_elt[cell[T]](util.none[T](),
                                              initial_capacity);

  ret deque[T](0u, 0u, 0u, v);
}
<|endoftext|>


<commit_before>/// The event system will have a trigger function that takes an
/// argument that decides if the event will be triggered this tick
/// or the next tick. The default should be next tick to prevent
/// inadvertent infinite loop bugs.
///
/// The event system can then schedule all events handlers that
/// do not mutate components to be run in parallel.
/// All handlers that do mutate the component list can be run
/// sequentially after that. Perhaps we can even schedule
/// those with non-overlapping mutable component lists to
/// run in parallel.
///
/// The event loop should trigger every n ms and execute any
/// events that are queued up. Every event has a function
/// that is called by the trigger! macro that puts the event
/// on the queue.
///
use std::collections::{ HashSet, HashMap };
use std::any::{ Any, TypeId };
use shared_mutex::{ SharedMutex };

pub mod example;

pub trait Handler {
	fn run(self, Vec<&Any>, Vec<&mut Any>);
	fn component_types(self) -> Vec<TypeId>;
	fn mut_component_types(self) -> Vec<TypeId>;
}

#[derive(Clone)]
pub struct Event {
	pub name: String,
	pub get_handler_instances: fn () -> Vec<Box<Handler>>
}

// The new events sets contain the events that have data in their queues so
// are ready to be ran.
lazy_static! {
	pub static ref THIS_TICK_NEW_EVENTS: SharedMutex<HashSet<String>> = SharedMutex::new(HashSet::new());
	pub static ref NEXT_TICK_NEW_EVENTS: SharedMutex<HashSet<String>> = SharedMutex::new(HashSet::new());
	pub static ref REGISTERED_EVENTS: SharedMutex<HashMap<String, Event>> = SharedMutex::new(HashMap::new());
}

pub fn trigger_this_tick(event_name: &String) {
	let mut new_events_set = THIS_TICK_NEW_EVENTS.write().expect("THIS_TICK_NEW_EVENTS mutex was corrupted.");
	new_events_set.insert(event_name.clone());
}

pub fn trigger_next_tick(event_name: &String) {
	let mut new_events_set = NEXT_TICK_NEW_EVENTS.write().expect("NEXT_TICK_NEW_EVENTS mutex was corrupted.");
	new_events_set.insert(event_name.clone());
}

pub fn register_event(event : Event) {
	let mut events = REGISTERED_EVENTS.write().expect("REGISTERED_EVENTS mutex was corrupted.");
	events.insert(event.name.clone(), event);
}

// Runs a single iteration of the event system. Can be run in a loop to process events
// continuously, but should be interleaved with `next_tick` to progress properly.
pub fn run_events() {
	let events = {
		let event_names = {
			let mut event_names_lock = THIS_TICK_NEW_EVENTS.write().expect("THIS_TICK_NEW_EVENTS mutex was corrupted");
			event_names_lock.drain().collect()
		};

		let events_lock = REGISTERED_EVENTS.read().expect("REGISTERED_EVENTS mutex was corrupted");

		event_names.iter().map(|n|
			events_lock.get(&*n).cloned().expect("Unknown event triggered")
		)
	};
	// Then we get the handlers for the ticks
	// for each handler
	// {
	//  	we obtain the correct component locks
	// 		we run the handlers
	// }
}

// Progresses the system to the next tick.
// Interleave `next_tick` between `run_events` invocations to make sure events that are
// scheduled to run only once per tick are triggered.
// A good scheme could be to run `next_tick` every 16ms, while `run_events` is ran continuously.
pub fn next_tick() {
	// get NEXT_TICK_NEW_EVENTS
	// get THIS_TICK_NEW_EVENTS
	// append NEXT_TICK_NEW_EVENTS to THIS_TICK_NEW_EVENTS
	// same for queues
}

#[macro_export]
macro_rules! event {
	( $name:ident, $( $field_name:ident : $field_typ:ty ),* ) => (
		pub mod $name {
			use shared_mutex::{ SharedMutex };
			use std::any::{ Any, TypeId };
			use entity_rust::events;
			use uuid::Uuid;

			/// Example component
			#[derive(PartialEq,Eq,Clone)]
			pub struct Data {
				$(pub $field_name : $field_typ),*
			}

			pub type HandlerFn = fn(Vec<Data>, Vec<&Any>, Vec<&mut Any>);

			pub struct Handler {
				handler_fn: HandlerFn,
				component_types: Vec<TypeId>,
				mut_component_types: Vec<TypeId>
			}

			pub struct HandlerInstance {
				handler_fn: HandlerFn,
				component_types: Vec<TypeId>,
				mut_component_types: Vec<TypeId>,
				data: Vec<Data>
			}

			impl HandlerInstance {
				pub fn new(h: &Handler, d: Vec<Data>) -> HandlerInstance {
					HandlerInstance {
						handler_fn: h.handler_fn,
						// TODO are these clones really necessary? would be cool if they could be static refs
						component_types: h.component_types.clone(),
						mut_component_types: h.mut_component_types.clone(),
						data: d
					}
				}
			}

			impl events::Handler for HandlerInstance {
				fn run(self, components: Vec<&Any>, mut_components: Vec<&mut Any>) {
					(self.handler_fn)(self.data, components, mut_components)
				}

				fn component_types(self) -> Vec<TypeId> { self.component_types }
				fn mut_component_types(self) -> Vec<TypeId> { self.mut_component_types }
			}

			lazy_static! {
				/// EVENT_UUID is used internally to index events, is randomly
				/// generated at first access.
				pub static ref EVENT_UUID: String = Uuid::new_v4().simple().to_string();
				pub static ref HANDLERS: SharedMutex<Vec<Handler>> = SharedMutex::new(vec![]);
				pub static ref THIS_TICK_DATA: SharedMutex<Vec<Data>> = SharedMutex::new(vec![]);
				pub static ref NEXT_TICK_DATA: SharedMutex<Vec<Data>> = SharedMutex::new(vec![]);
			}

			/// Listeners are a list of functions that should be called by trigger
			pub fn trigger(argument: Data) {
				let mut data = THIS_TICK_DATA.write().expect("THIS_TICK_DATA mutex corrupted");
				data.push(argument);

				events::trigger_this_tick(&*EVENT_UUID);
			}

			pub fn register_handler(handler_fn: HandlerFn, component_types: Vec<TypeId>, mut_component_types: Vec<TypeId>) {
				let mut handlers = HANDLERS.write().expect("Events HANDLERS mutex corrupted");
				let handler = Handler {
					handler_fn : handler_fn,
					// TODO are these clones really necessary? would be cool if they could be static refs
					component_types : component_types.clone(),
					mut_component_types : mut_component_types.clone()
				};
				handlers.push(handler);

				let event = events::Event {
					name: (&*EVENT_UUID).clone(),
					get_handler_instances: get_handler_instances
				};

				events::register_event(event)
			}

			pub fn get_handler_instances() -> Vec<Box<events::Handler>> {
				let mut data_old = THIS_TICK_DATA.write().expect("TICK DATA mutex corrupted");
				let data : Vec<Data> = data_old.drain(..).collect();

				let handlers_lock = HANDLERS.read().expect("HANDLERS mutex corrupted");
				handlers_lock.iter().map(|h|
					//TODO eliminate this data.clone
					Box::new(HandlerInstance::new(h, data.clone())) as Box<events::Handler>
				).collect()
			}
		}
	)
}

/// Queues an event to be dispatched.
/// This means that the argument is put into the trigger queue for the
/// event and the event handlers will be invoked either at the next run loop.
/// or immediately.
macro_rules! trigger {
	() => ()
}
<commit_msg>scope run_events nicely<commit_after>/// The event system will have a trigger function that takes an
/// argument that decides if the event will be triggered this tick
/// or the next tick. The default should be next tick to prevent
/// inadvertent infinite loop bugs.
///
/// The event system can then schedule all events handlers that
/// do not mutate components to be run in parallel.
/// All handlers that do mutate the component list can be run
/// sequentially after that. Perhaps we can even schedule
/// those with non-overlapping mutable component lists to
/// run in parallel.
///
/// The event loop should trigger every n ms and execute any
/// events that are queued up. Every event has a function
/// that is called by the trigger! macro that puts the event
/// on the queue.
///
use std::collections::{ HashSet, HashMap };
use std::any::{ Any, TypeId };
use shared_mutex::{ SharedMutex };

pub mod example;

pub trait Handler {
	fn run(self, Vec<&Any>, Vec<&mut Any>);
	fn component_types(self) -> Vec<TypeId>;
	fn mut_component_types(self) -> Vec<TypeId>;
}

#[derive(Clone)]
pub struct Event {
	pub name: String,
	pub get_handler_instances: fn () -> Vec<Box<Handler>>
}

// The new events sets contain the events that have data in their queues so
// are ready to be ran.
lazy_static! {
	pub static ref THIS_TICK_NEW_EVENTS: SharedMutex<HashSet<String>> = SharedMutex::new(HashSet::new());
	pub static ref NEXT_TICK_NEW_EVENTS: SharedMutex<HashSet<String>> = SharedMutex::new(HashSet::new());
	pub static ref REGISTERED_EVENTS: SharedMutex<HashMap<String, Event>> = SharedMutex::new(HashMap::new());
}

pub fn trigger_this_tick(event_name: &String) {
	let mut new_events_set = THIS_TICK_NEW_EVENTS.write().expect("THIS_TICK_NEW_EVENTS mutex was corrupted.");
	new_events_set.insert(event_name.clone());
}

pub fn trigger_next_tick(event_name: &String) {
	let mut new_events_set = NEXT_TICK_NEW_EVENTS.write().expect("NEXT_TICK_NEW_EVENTS mutex was corrupted.");
	new_events_set.insert(event_name.clone());
}

pub fn register_event(event : Event) {
	let mut events = REGISTERED_EVENTS.write().expect("REGISTERED_EVENTS mutex was corrupted.");
	events.insert(event.name.clone(), event);
}

// Runs a single iteration of the event system. Can be run in a loop to process events
// continuously, but should be interleaved with `next_tick` to progress properly.
pub fn run_events() {
	let events : Vec<Event>;
	{
		let event_names : Vec<String>;
		{
			let mut event_names_lock = THIS_TICK_NEW_EVENTS.write().expect("THIS_TICK_NEW_EVENTS mutex was corrupted");
			event_names = event_names_lock.drain().collect();
		}

		let events_lock = REGISTERED_EVENTS.read().expect("REGISTERED_EVENTS mutex was corrupted");
		events = event_names.iter().map(|n|
			events_lock.get(&*n).cloned().expect("Unknown event triggered")
		).collect();
	}
	// Then we get the handlers for the ticks
	// for each handler
	// {
	//  	we obtain the correct component locks
	// 		we run the handlers
	// }
}

// Progresses the system to the next tick.
// Interleave `next_tick` between `run_events` invocations to make sure events that are
// scheduled to run only once per tick are triggered.
// A good scheme could be to run `next_tick` every 16ms, while `run_events` is ran continuously.
pub fn next_tick() {
	// get NEXT_TICK_NEW_EVENTS
	// get THIS_TICK_NEW_EVENTS
	// append NEXT_TICK_NEW_EVENTS to THIS_TICK_NEW_EVENTS
	// same for queues
}

#[macro_export]
macro_rules! event {
	( $name:ident, $( $field_name:ident : $field_typ:ty ),* ) => (
		pub mod $name {
			use shared_mutex::{ SharedMutex };
			use std::any::{ Any, TypeId };
			use entity_rust::events;
			use uuid::Uuid;

			/// Example component
			#[derive(PartialEq,Eq,Clone)]
			pub struct Data {
				$(pub $field_name : $field_typ),*
			}

			pub type HandlerFn = fn(Vec<Data>, Vec<&Any>, Vec<&mut Any>);

			pub struct Handler {
				handler_fn: HandlerFn,
				component_types: Vec<TypeId>,
				mut_component_types: Vec<TypeId>
			}

			pub struct HandlerInstance {
				handler_fn: HandlerFn,
				component_types: Vec<TypeId>,
				mut_component_types: Vec<TypeId>,
				data: Vec<Data>
			}

			impl HandlerInstance {
				pub fn new(h: &Handler, d: Vec<Data>) -> HandlerInstance {
					HandlerInstance {
						handler_fn: h.handler_fn,
						// TODO are these clones really necessary? would be cool if they could be static refs
						component_types: h.component_types.clone(),
						mut_component_types: h.mut_component_types.clone(),
						data: d
					}
				}
			}

			impl events::Handler for HandlerInstance {
				fn run(self, components: Vec<&Any>, mut_components: Vec<&mut Any>) {
					(self.handler_fn)(self.data, components, mut_components)
				}

				fn component_types(self) -> Vec<TypeId> { self.component_types }
				fn mut_component_types(self) -> Vec<TypeId> { self.mut_component_types }
			}

			lazy_static! {
				/// EVENT_UUID is used internally to index events, is randomly
				/// generated at first access.
				pub static ref EVENT_UUID: String = Uuid::new_v4().simple().to_string();
				pub static ref HANDLERS: SharedMutex<Vec<Handler>> = SharedMutex::new(vec![]);
				pub static ref THIS_TICK_DATA: SharedMutex<Vec<Data>> = SharedMutex::new(vec![]);
				pub static ref NEXT_TICK_DATA: SharedMutex<Vec<Data>> = SharedMutex::new(vec![]);
			}

			/// Listeners are a list of functions that should be called by trigger
			pub fn trigger(argument: Data) {
				let mut data = THIS_TICK_DATA.write().expect("THIS_TICK_DATA mutex corrupted");
				data.push(argument);

				events::trigger_this_tick(&*EVENT_UUID);
			}

			pub fn register_handler(handler_fn: HandlerFn, component_types: Vec<TypeId>, mut_component_types: Vec<TypeId>) {
				let mut handlers = HANDLERS.write().expect("Events HANDLERS mutex corrupted");
				let handler = Handler {
					handler_fn : handler_fn,
					// TODO are these clones really necessary? would be cool if they could be static refs
					component_types : component_types.clone(),
					mut_component_types : mut_component_types.clone()
				};
				handlers.push(handler);

				let event = events::Event {
					name: (&*EVENT_UUID).clone(),
					get_handler_instances: get_handler_instances
				};

				events::register_event(event)
			}

			pub fn get_handler_instances() -> Vec<Box<events::Handler>> {
				let mut data_old = THIS_TICK_DATA.write().expect("TICK DATA mutex corrupted");
				let data : Vec<Data> = data_old.drain(..).collect();

				let handlers_lock = HANDLERS.read().expect("HANDLERS mutex corrupted");
				handlers_lock.iter().map(|h|
					//TODO eliminate this data.clone
					Box::new(HandlerInstance::new(h, data.clone())) as Box<events::Handler>
				).collect()
			}
		}
	)
}

/// Queues an event to be dispatched.
/// This means that the argument is put into the trigger queue for the
/// event and the event handlers will be invoked either at the next run loop.
/// or immediately.
macro_rules! trigger {
	() => ()
}
<|endoftext|>


<commit_before>/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

// spell-checker:ignore (acronyms/names) Gehring
// spell-checker:ignore (rustlang/crates) clippy concat rustlang termwidth textwrap
// spell-checker:ignore (uutils) coreutils sigpipe uucore uumain uutils
// spell-checker:ignore (shell) busybox symlinks

extern crate lazy_static;
extern crate textwrap;
extern crate uucore;

use lazy_static::lazy_static;
use std::collections::hash_map::HashMap;
use std::io::Write;

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

lazy_static! {
    static ref BINARY_PATH: std::path::PathBuf = {
        // support symlinks by using args[0], when possible, with fallback to current_exe()
        match std::env::args().next() {
            Some(ref s) if !s.is_empty() => std::path::PathBuf::from(s),
            _ => std::env::current_exe().unwrap(),
        }
    };
    static ref NAME: &'static str = &*BINARY_PATH.file_stem().unwrap().to_str().unwrap();
}

include!(concat!(env!("OUT_DIR"), "/uutils_map.rs"));

fn usage(utils: &UtilityMap) {
    println!("{} {} (multi-call binary)\n", *NAME, VERSION);
    println!("Usage: {} [function [arguments...]]\n", *NAME);
    println!("Currently defined functions/utilities:\n");
    #[allow(clippy::map_clone)]
    let mut utils: Vec<&str> = utils.keys().map(|&s| s).collect();
    utils.sort();
    let display_list = utils.join(", ");
    let width = std::cmp::min(textwrap::termwidth(), 100) - 4 * 2; // (opinion/heuristic) max 100 chars wide with 4 character side indentions
    println!(
        "{}",
        textwrap::indent(&textwrap::fill(&display_list, width), "    ")
    );
}

fn main() {
    uucore::panic::install_sigpipe_hook();

    let utils = util_map();
    let mut args: Vec<String> = uucore::args().collect();

    let binary = &BINARY_PATH;
    let binary_as_util = binary.file_stem().unwrap().to_str().unwrap();

    // binary name equals util name?
    if let Some(&uumain) = utils.get(binary_as_util) {
        std::process::exit(uumain(args));
    }

    // binary name equals prefixed util name?
    // * prefix/stem may be any string ending in a non-alphanumeric character
    if let Some(util) = utils.keys().find(|util| {
        binary_as_util.ends_with(*util)
            && !(&binary_as_util[..binary_as_util.len() - (*util).len()])
                .ends_with(char::is_alphanumeric)
    }) {
        // prefixed util => replace 0th (aka, executable name) argument
        args[0] = (*util).to_owned();
    } else {
        // unmatched binary name => regard as multi-binary container and advance argument list
        args.remove(0);
    }

    // 0th argument equals util name?
    if !args.is_empty() {
        let util = &args[0][..];

        match utils.get(util) {
            Some(&uumain) => {
                std::process::exit(uumain(args.clone()));
            }
            None => {
                if &args[0][..] == "--help" || &args[0][..] == "-h" {
                    // see if they want help on a specific util
                    if args.len() >= 2 {
                        let util = &args[1][..];
                        match utils.get(util) {
                            Some(&uumain) => {
                                let code = uumain(vec![util.to_owned(), "--help".to_owned()]);
                                std::io::stdout().flush().expect("could not flush stdout");
                                std::process::exit(code);
                            }
                            None => {
                                println!("{}: function/utility not found", util);
                                std::process::exit(1);
                            }
                        }
                    }
                    usage(&utils);
                    std::process::exit(0);
                } else {
                    println!("{}: function/utility not found", util);
                    std::process::exit(1);
                }
            }
        }
    } else {
        // no arguments provided
        usage(&utils);
        std::process::exit(0);
    }
}
<commit_msg>change ~ `install_sigpipe_hook()` => `mute_sigpipe_panic()` (from uucore v0.0.4)<commit_after>/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

// spell-checker:ignore (acronyms/names) Gehring
// spell-checker:ignore (rustlang/crates) clippy concat rustlang termwidth textwrap
// spell-checker:ignore (uutils) coreutils sigpipe uucore uumain uutils
// spell-checker:ignore (shell) busybox symlinks

extern crate lazy_static;
extern crate textwrap;
extern crate uucore;

use lazy_static::lazy_static;
use std::collections::hash_map::HashMap;
use std::io::Write;

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

lazy_static! {
    static ref BINARY_PATH: std::path::PathBuf = {
        // support symlinks by using args[0], when possible, with fallback to current_exe()
        match std::env::args().next() {
            Some(ref s) if !s.is_empty() => std::path::PathBuf::from(s),
            _ => std::env::current_exe().unwrap(),
        }
    };
    static ref NAME: &'static str = &*BINARY_PATH.file_stem().unwrap().to_str().unwrap();
}

include!(concat!(env!("OUT_DIR"), "/uutils_map.rs"));

fn usage(utils: &UtilityMap) {
    println!("{} {} (multi-call binary)\n", *NAME, VERSION);
    println!("Usage: {} [function [arguments...]]\n", *NAME);
    println!("Currently defined functions/utilities:\n");
    #[allow(clippy::map_clone)]
    let mut utils: Vec<&str> = utils.keys().map(|&s| s).collect();
    utils.sort();
    let display_list = utils.join(", ");
    let width = std::cmp::min(textwrap::termwidth(), 100) - 4 * 2; // (opinion/heuristic) max 100 chars wide with 4 character side indentions
    println!(
        "{}",
        textwrap::indent(&textwrap::fill(&display_list, width), "    ")
    );
}

fn main() {
    uucore::panic::mute_sigpipe_panic();

    let utils = util_map();
    let mut args: Vec<String> = uucore::args().collect();

    let binary = &BINARY_PATH;
    let binary_as_util = binary.file_stem().unwrap().to_str().unwrap();

    // binary name equals util name?
    if let Some(&uumain) = utils.get(binary_as_util) {
        std::process::exit(uumain(args));
    }

    // binary name equals prefixed util name?
    // * prefix/stem may be any string ending in a non-alphanumeric character
    if let Some(util) = utils.keys().find(|util| {
        binary_as_util.ends_with(*util)
            && !(&binary_as_util[..binary_as_util.len() - (*util).len()])
                .ends_with(char::is_alphanumeric)
    }) {
        // prefixed util => replace 0th (aka, executable name) argument
        args[0] = (*util).to_owned();
    } else {
        // unmatched binary name => regard as multi-binary container and advance argument list
        args.remove(0);
    }

    // 0th argument equals util name?
    if !args.is_empty() {
        let util = &args[0][..];

        match utils.get(util) {
            Some(&uumain) => {
                std::process::exit(uumain(args.clone()));
            }
            None => {
                if &args[0][..] == "--help" || &args[0][..] == "-h" {
                    // see if they want help on a specific util
                    if args.len() >= 2 {
                        let util = &args[1][..];
                        match utils.get(util) {
                            Some(&uumain) => {
                                let code = uumain(vec![util.to_owned(), "--help".to_owned()]);
                                std::io::stdout().flush().expect("could not flush stdout");
                                std::process::exit(code);
                            }
                            None => {
                                println!("{}: function/utility not found", util);
                                std::process::exit(1);
                            }
                        }
                    }
                    usage(&utils);
                    std::process::exit(0);
                } else {
                    println!("{}: function/utility not found", util);
                    std::process::exit(1);
                }
            }
        }
    } else {
        // no arguments provided
        usage(&utils);
        std::process::exit(0);
    }
}
<|endoftext|>


<commit_before>extern crate csv;
extern crate getopts;

use getopts::Options;
use std::io::{self, Write};
use std::f32;

mod common;

fn ask_mileage() -> u32 {

    print!("Enter the mileage you want to estimate: ");
    io::stdout().flush().unwrap();

    let mut buffer = String::new();
    io::stdin().read_line(&mut buffer).ok().expect("Failed to read stdin");
    buffer = buffer.split_whitespace().nth(0).expect("Failed to get first word").to_string();
    buffer.parse().ok().expect("Wanted a positive number")
}

pub fn retrieve_thetas(file: &str) -> Option<(f32, f32)> {

    if let Ok(mut rdr) = csv::Reader::from_file(file) {

        if let Ok(ret) = rdr.decode().nth(0).unwrap() {
            return Some(ret);
        }
    }
    None
}

pub fn retrieve_min_max(file: &str) -> Option<(f32, f32)> {

    if let Ok(mut rdr) = csv::Reader::from_file(file) {

        if let Ok(ret) = rdr.decode().nth(0).unwrap() {
            return Some(ret);
        }
    }
    None
}

fn print_usage(program: &str, opts: Options) {

    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {

    let args: Vec<String> = std::env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("m", "mileage", "set directly the mileage you want to estimate, default `stdin`", "VALUE");
    opts.optopt("", "tmp-file-thetas", format!("set the file where you want to read thetas values, default {}", common::TMP_FILE_THETAS).as_ref(), "FILE");
    opts.optopt("", "tmp-file-min-max", format!("set the file where you want to read min-max values, default {}", common::TMP_FILE_MIN_MAX).as_ref(), "FILE");
    opts.optflag("g", "graph", "display a graph representing the data and the curve found");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }

    let thetas_file = matches.opt_str("tmp-file-thetas").unwrap_or(common::TMP_FILE_THETAS.to_string());
    let min_max_file = matches.opt_str("tmp-file-min-max").unwrap_or(common::TMP_FILE_MIN_MAX.to_string());

    // retrieving data
    let (theta0, theta1) = retrieve_thetas(thetas_file.as_ref()).unwrap_or((0_f32, 0_f32));
    let (min, max) = retrieve_min_max(min_max_file.as_ref()).unwrap_or((0_f32, f32::INFINITY));

    let mileage: f32 = match matches.opt_str("m") {
        Some(value) => value.parse().ok().expect("Option `-m` need a number..."),
        None => ask_mileage() as f32
    };

    let normed_mileage = common::normalize(mileage, min, max);

    let estimated = common::estimate_price(normed_mileage, theta0, theta1);
    println!("Estimated price is `{}`", estimated);
}
<commit_msg>compute error percentage for training<commit_after>extern crate csv;
extern crate getopts;

use getopts::Options;
use std::io::{self, Write};
use std::f32;

mod common;

fn ask_mileage() -> u32 {

    print!("Enter the mileage you want to estimate: ");
    io::stdout().flush().unwrap();

    let mut buffer = String::new();
    io::stdin().read_line(&mut buffer).ok().expect("Failed to read stdin");
    buffer = buffer.split_whitespace().nth(0).expect("Failed to get first word").to_string();
    buffer.parse().ok().expect("Wanted a positive number")
}

pub fn retrieve_thetas(file: &str) -> Option<(f32, f32)> {

    if let Ok(mut rdr) = csv::Reader::from_file(file) {

        if let Ok(ret) = rdr.decode().nth(0).unwrap() {
            return Some(ret);
        }
    }
    None
}

pub fn retrieve_min_max(file: &str) -> Option<(f32, f32)> {

    if let Ok(mut rdr) = csv::Reader::from_file(file) {

        if let Ok(ret) = rdr.decode().nth(0).unwrap() {
            return Some(ret);
        }
    }
    None
}

fn print_usage(program: &str, opts: Options) {

    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {

    let args: Vec<String> = std::env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("m", "mileage", "set directly the mileage you want to estimate, default `stdin`", "VALUE");
    opts.optopt("", "tmp-file-thetas", format!("set the file where you want to read thetas values, default {}", common::TMP_FILE_THETAS).as_ref(), "FILE");
    opts.optopt("", "tmp-file-min-max", format!("set the file where you want to read min-max values, default {}", common::TMP_FILE_MIN_MAX).as_ref(), "FILE");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }

    let thetas_file = matches.opt_str("tmp-file-thetas").unwrap_or(common::TMP_FILE_THETAS.to_string());
    let min_max_file = matches.opt_str("tmp-file-min-max").unwrap_or(common::TMP_FILE_MIN_MAX.to_string());

    // retrieving data
    let (theta0, theta1) = retrieve_thetas(thetas_file.as_ref()).unwrap_or((0_f32, 0_f32));
    let (min, max) = retrieve_min_max(min_max_file.as_ref()).unwrap_or((0_f32, f32::INFINITY));

    let mileage: f32 = match matches.opt_str("m") {
        Some(value) => value.parse().ok().expect("Option `-m` need a number..."),
        None => ask_mileage() as f32
    };

    let normed_mileage = common::normalize(mileage, min, max);

    let estimated = common::estimate_price(normed_mileage, theta0, theta1);
    println!("Estimated price is `{}`", estimated);
}
<|endoftext|>


<commit_before>//! `cargo add`

#![deny(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts, trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces, unused_qualifications)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

extern crate docopt;
extern crate rustc_serialize;
extern crate pad;
extern crate toml;
#[macro_use]
extern crate quick_error;

use std::error::Error;
use std::io::{self, Write};
use std::process;

extern crate cargo_edit;
use cargo_edit::Manifest;

mod list;
mod list_error;
mod tree;

use list::list_section;
use list_error::ListError;
use tree::parse_lock_file as list_tree;

static USAGE: &'static str = r"
Usage:
    cargo list [--dev|--build] [options]
    cargo list --tree
    cargo list (-h|--help)
    cargo list --version

Options:
    --manifest-path=<path>  Path to the manifest to list dependencies of.
    --tree                  List dependencies recursively as tree.
    -h --help               Show this help page.
    --version               Show version.

Display a crate's dependencies using its Cargo.toml file.
";

/// Docopts input args.
#[derive(Debug, RustcDecodable)]
struct Args {
    /// dev-dependency
    flag_dev: bool,
    /// build-dependency
    flag_build: bool,
    /// Render tree of dependencies
    flag_tree: bool,
    /// `Cargo.toml` path
    flag_manifest_path: Option<String>,
    /// `--version`
    flag_version: bool,
}

impl Args {
    /// Get dependency section
    fn get_section(&self) -> &'static str {
        if self.flag_dev {
            "dev-dependencies"
        } else if self.flag_build {
            "build-dependencies"
        } else {
            "dependencies"
        }
    }
}

fn handle_list(args: &Args) -> Result<String, Box<Error>> {
    if args.flag_tree {
            let manifest = try!(Manifest::open_lock_file(&args.flag_manifest_path
                .as_ref()
                .map(|s| &s[..])));
            list_tree(&manifest)
        } else {
            let manifest = try!(Manifest::open(&args.flag_manifest_path.as_ref().map(|s| &s[..])));
            list_section(&manifest, args.get_section()).or_else(|err| match err {
                ListError::SectionMissing(..) => Ok("".into()),
                _ => Err(err),
            })
        }
        .map_err(From::from)
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.decode::<Args>())
        .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-list version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    match handle_list(&args) {
        Ok(list) => {
            println!("{}", list);
        }
        Err(err) => {
            writeln!(io::stderr(), "{}", err).unwrap();
            process::exit(1);
        }
    }
}
<commit_msg>-V is often short for --version<commit_after>//! `cargo add`

#![deny(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts, trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces, unused_qualifications)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

extern crate docopt;
extern crate rustc_serialize;
extern crate pad;
extern crate toml;
#[macro_use]
extern crate quick_error;

use std::error::Error;
use std::io::{self, Write};
use std::process;

extern crate cargo_edit;
use cargo_edit::Manifest;

mod list;
mod list_error;
mod tree;

use list::list_section;
use list_error::ListError;
use tree::parse_lock_file as list_tree;

static USAGE: &'static str = r"
Usage:
    cargo list [--dev|--build] [options]
    cargo list --tree
    cargo list (-h|--help)
    cargo list --version

Options:
    --manifest-path=<path>  Path to the manifest to list dependencies of.
    --tree                  List dependencies recursively as tree.
    -h --help               Show this help page.
    -V --version            Show version.

Display a crate's dependencies using its Cargo.toml file.
";

/// Docopts input args.
#[derive(Debug, RustcDecodable)]
struct Args {
    /// dev-dependency
    flag_dev: bool,
    /// build-dependency
    flag_build: bool,
    /// Render tree of dependencies
    flag_tree: bool,
    /// `Cargo.toml` path
    flag_manifest_path: Option<String>,
    /// `--version`
    flag_version: bool,
}

impl Args {
    /// Get dependency section
    fn get_section(&self) -> &'static str {
        if self.flag_dev {
            "dev-dependencies"
        } else if self.flag_build {
            "build-dependencies"
        } else {
            "dependencies"
        }
    }
}

fn handle_list(args: &Args) -> Result<String, Box<Error>> {
    if args.flag_tree {
            let manifest = try!(Manifest::open_lock_file(&args.flag_manifest_path
                .as_ref()
                .map(|s| &s[..])));
            list_tree(&manifest)
        } else {
            let manifest = try!(Manifest::open(&args.flag_manifest_path.as_ref().map(|s| &s[..])));
            list_section(&manifest, args.get_section()).or_else(|err| match err {
                ListError::SectionMissing(..) => Ok("".into()),
                _ => Err(err),
            })
        }
        .map_err(From::from)
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.decode::<Args>())
        .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-list version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    match handle_list(&args) {
        Ok(list) => {
            println!("{}", list);
        }
        Err(err) => {
            writeln!(io::stderr(), "{}", err).unwrap();
            process::exit(1);
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::Deref;
use std::rc::Rc;
use std::cell::RefCell;
use super::Position;
use super::GapBuffer;

/// Read-only wrapper for a `Position`, to allow field level access to a
/// buffer's cursor while simultaneously enforcing bounds-checking when
/// updating its value.
pub struct Cursor {
    pub data: Rc<RefCell<GapBuffer>>,
    pub position: Position,
}

impl Deref for Cursor {
    type Target = Position;

    fn deref(&self) -> &Position {
        &self.position
    }
}

impl Cursor {
    /// Moves the cursor to the specified location. The location is
    /// bounds-checked against the data and the cursor will not be
    /// updated if it is out-of-bounds.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::new();
    /// let in_bounds = scribe::buffer::Position{ line: 0, offset: 2 };
    /// let out_of_bounds = scribe::buffer::Position{ line: 2, offset: 2 };
    /// buffer.insert("scribe");
    ///
    /// buffer.cursor.move_to(in_bounds);
    /// assert_eq!(buffer.cursor.line, 0);
    /// assert_eq!(buffer.cursor.offset, 2);
    ///
    /// buffer.cursor.move_to(out_of_bounds);
    /// assert_eq!(buffer.cursor.line, 0);
    /// assert_eq!(buffer.cursor.offset, 2);
    /// ```
    pub fn move_to(&mut self, position: Position) -> bool {
        if self.data.borrow().in_bounds(&position) {
            self.position = position;
            return true
        }
        false
    }

    /// Decrements the cursor line. The location is bounds-checked against
    /// the data and the cursor will not be updated if it is out-of-bounds.
    pub fn move_up(&mut self) {
        let target_line = self.line-1;
        let new_position = Position{ line: target_line, offset: self.offset };

        // Don't even bother if the target line is negative.
        if target_line < 0 { return }

        // Try moving to the same offset on the line above, falling back to its EOL.
        if self.move_to(new_position) == false {
            let mut target_offset = 0;
            for (line_number, line) in self.data.borrow().to_string().lines().enumerate() {
                if line_number == target_line {
                    target_offset = line.len();
                }
            }
            self.move_to(Position{ line: target_line, offset: target_offset });
        }
    }

    /// Increments the cursor line. The location is bounds-checked against
    /// the data and the cursor will not be updated if it is out-of-bounds.
    pub fn move_down(&mut self) {
        let target_line = self.line+1;
        let new_position = Position{ line: target_line, offset: self.offset };

        // Try moving to the same offset on the line below, falling back to its EOL.
        if self.move_to(new_position) == false {
            let mut target_offset = 0;
            for (line_number, line) in self.data.borrow().to_string().lines().enumerate() {
                if line_number == target_line {
                    target_offset = line.len();
                }
            }
            self.move_to(Position{ line: target_line, offset: target_offset });
        }
    }

    /// Decrements the cursor offset. The location is bounds-checked against
    /// the data and the cursor will not be updated if it is out-of-bounds.
    pub fn move_left(&mut self) {
        let new_position = Position{ line: self.line, offset: self.offset-1 };
        self.move_to(new_position);
    }

    /// Increments the cursor offset. The location is bounds-checked against
    /// the data and the cursor will not be updated if it is out-of-bounds.
    pub fn move_right(&mut self) {
        let new_position = Position{ line: self.line, offset: self.offset+1 };
        self.move_to(new_position);
    }

    /// Sets the cursor offset to 0: the start of the current line.
    pub fn move_to_start_of_line(&mut self) {
        let new_position = Position{ line: self.line, offset: 0 };
        self.move_to(new_position);
    }
}

#[cfg(test)]
mod tests {
    use super::Cursor;
    use super::super::gap_buffer;
    use super::super::Position;
    use std::rc::Rc;
    use std::cell::RefCell;

    #[test]
    fn move_up_goes_to_EOL_if_offset_would_be_out_of_range() {
        let mut buffer = Rc::new(RefCell::new(gap_buffer::new("This is a test.\nAnother line that is longer.".to_string())));
        let position = Position{ line: 1, offset: 20 };
        let mut cursor = Cursor{ data: buffer, position: position };
        cursor.move_up();
        assert_eq!(cursor.line, 0);
        assert_eq!(cursor.offset, 15);
    }

    #[test]
    fn move_down_goes_to_EOL_if_offset_would_be_out_of_range() {
        let mut buffer = Rc::new(RefCell::new(gap_buffer::new("Another line that is longer.\nThis is a test.".to_string())));
        let position = Position{ line: 0, offset: 20 };
        let mut cursor = Cursor{ data: buffer, position: position };
        cursor.move_down();
        assert_eq!(cursor.line, 1);
        assert_eq!(cursor.offset, 15);
    }

    #[test]
    fn move_to_start_of_line_sets_offset_to_zero() {
        let mut buffer = Rc::new(RefCell::new(gap_buffer::new("This is a test.\nAnother line.".to_string())));
        let position = Position{ line: 1, offset: 5 };
        let mut cursor = Cursor{ data: buffer, position: position };
        cursor.move_to_start_of_line();
        assert_eq!(cursor.line, 1);
        assert_eq!(cursor.offset, 0);
    }
}
<commit_msg>Implement move_to_end_of_line for cursor type.<commit_after>use std::ops::Deref;
use std::rc::Rc;
use std::cell::RefCell;
use super::Position;
use super::GapBuffer;

/// Read-only wrapper for a `Position`, to allow field level access to a
/// buffer's cursor while simultaneously enforcing bounds-checking when
/// updating its value.
pub struct Cursor {
    pub data: Rc<RefCell<GapBuffer>>,
    pub position: Position,
}

impl Deref for Cursor {
    type Target = Position;

    fn deref(&self) -> &Position {
        &self.position
    }
}

impl Cursor {
    /// Moves the cursor to the specified location. The location is
    /// bounds-checked against the data and the cursor will not be
    /// updated if it is out-of-bounds.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::new();
    /// let in_bounds = scribe::buffer::Position{ line: 0, offset: 2 };
    /// let out_of_bounds = scribe::buffer::Position{ line: 2, offset: 2 };
    /// buffer.insert("scribe");
    ///
    /// buffer.cursor.move_to(in_bounds);
    /// assert_eq!(buffer.cursor.line, 0);
    /// assert_eq!(buffer.cursor.offset, 2);
    ///
    /// buffer.cursor.move_to(out_of_bounds);
    /// assert_eq!(buffer.cursor.line, 0);
    /// assert_eq!(buffer.cursor.offset, 2);
    /// ```
    pub fn move_to(&mut self, position: Position) -> bool {
        if self.data.borrow().in_bounds(&position) {
            self.position = position;
            return true
        }
        false
    }

    /// Decrements the cursor line. The location is bounds-checked against
    /// the data and the cursor will not be updated if it is out-of-bounds.
    pub fn move_up(&mut self) {
        let target_line = self.line-1;
        let new_position = Position{ line: target_line, offset: self.offset };

        // Don't even bother if the target line is negative.
        if target_line < 0 { return }

        // Try moving to the same offset on the line above, falling back to its EOL.
        if self.move_to(new_position) == false {
            let mut target_offset = 0;
            for (line_number, line) in self.data.borrow().to_string().lines().enumerate() {
                if line_number == target_line {
                    target_offset = line.len();
                }
            }
            self.move_to(Position{ line: target_line, offset: target_offset });
        }
    }

    /// Increments the cursor line. The location is bounds-checked against
    /// the data and the cursor will not be updated if it is out-of-bounds.
    pub fn move_down(&mut self) {
        let target_line = self.line+1;
        let new_position = Position{ line: target_line, offset: self.offset };

        // Try moving to the same offset on the line below, falling back to its EOL.
        if self.move_to(new_position) == false {
            let mut target_offset = 0;
            for (line_number, line) in self.data.borrow().to_string().lines().enumerate() {
                if line_number == target_line {
                    target_offset = line.len();
                }
            }
            self.move_to(Position{ line: target_line, offset: target_offset });
        }
    }

    /// Decrements the cursor offset. The location is bounds-checked against
    /// the data and the cursor will not be updated if it is out-of-bounds.
    pub fn move_left(&mut self) {
        let new_position = Position{ line: self.line, offset: self.offset-1 };
        self.move_to(new_position);
    }

    /// Increments the cursor offset. The location is bounds-checked against
    /// the data and the cursor will not be updated if it is out-of-bounds.
    pub fn move_right(&mut self) {
        let new_position = Position{ line: self.line, offset: self.offset+1 };
        self.move_to(new_position);
    }

    /// Sets the cursor offset to 0: the start of the current line.
    pub fn move_to_start_of_line(&mut self) {
        let new_position = Position{ line: self.line, offset: 0 };
        self.move_to(new_position);
    }

    /// Moves the cursor offset to after the last character on the current line.
    pub fn move_to_end_of_line(&mut self) {
        let data = self.data.borrow().to_string();
        let current_line = data.lines().nth(self.line);
        match current_line {
            Some(line) => {
                let new_position = Position{ line: self.line, offset: line.len() };
                self.move_to(new_position);
            },
            None => (),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Cursor;
    use super::super::gap_buffer;
    use super::super::Position;
    use std::rc::Rc;
    use std::cell::RefCell;

    #[test]
    fn move_up_goes_to_EOL_if_offset_would_be_out_of_range() {
        let mut buffer = Rc::new(RefCell::new(gap_buffer::new("This is a test.\nAnother line that is longer.".to_string())));
        let position = Position{ line: 1, offset: 20 };
        let mut cursor = Cursor{ data: buffer, position: position };
        cursor.move_up();
        assert_eq!(cursor.line, 0);
        assert_eq!(cursor.offset, 15);
    }

    #[test]
    fn move_down_goes_to_EOL_if_offset_would_be_out_of_range() {
        let mut buffer = Rc::new(RefCell::new(gap_buffer::new("Another line that is longer.\nThis is a test.".to_string())));
        let position = Position{ line: 0, offset: 20 };
        let mut cursor = Cursor{ data: buffer, position: position };
        cursor.move_down();
        assert_eq!(cursor.line, 1);
        assert_eq!(cursor.offset, 15);
    }

    #[test]
    fn move_to_start_of_line_sets_offset_to_zero() {
        let mut buffer = Rc::new(RefCell::new(gap_buffer::new("This is a test.\nAnother line.".to_string())));
        let position = Position{ line: 1, offset: 5 };
        let mut cursor = Cursor{ data: buffer, position: position };
        cursor.move_to_start_of_line();
        assert_eq!(cursor.line, 1);
        assert_eq!(cursor.offset, 0);
    }

    #[test]
    fn move_to_end_of_line_sets_offset_the_line_length() {
        let mut buffer = Rc::new(RefCell::new(gap_buffer::new("This is a test.\nAnother line.".to_string())));
        let position = Position{ line: 0, offset: 5 };
        let mut cursor = Cursor{ data: buffer, position: position };
        cursor.move_to_end_of_line();
        assert_eq!(cursor.line, 0);
        assert_eq!(cursor.offset, 15);
    }
}
<|endoftext|>