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

//! Global style data

use context::StyleSystemOptions;
use gecko_bindings::bindings::{Gecko_RegisterProfilerThread, Gecko_UnregisterProfilerThread};
use gecko_bindings::bindings::Gecko_SetJemallocThreadLocalArena;
use num_cpus;
use parallel::STYLE_THREAD_STACK_SIZE_KB;
use rayon;
use shared_lock::SharedRwLock;
use std::cmp;
use std::env;
use std::ffi::CString;
use thread_state;

/// Global style data
pub struct GlobalStyleData {
    /// Shared RWLock for CSSOM objects
    pub shared_lock: SharedRwLock,

    /// Global style system options determined by env vars.
    pub options: StyleSystemOptions,
}

/// Global thread pool
pub struct StyleThreadPool {
    /// How many threads parallel styling can use.
    pub num_threads: usize,

    /// The parallel styling thread pool.
    pub style_thread_pool: Option<rayon::ThreadPool>,
}

fn thread_name(index: usize) -> String {
    format!("StyleThread#{}", index)
}

fn thread_startup(index: usize) {
    thread_state::initialize_layout_worker_thread();
    unsafe {
        Gecko_SetJemallocThreadLocalArena(true);
    }
    let name = thread_name(index);
    let name = CString::new(name).unwrap();
    unsafe {
        // Gecko_RegisterProfilerThread copies the passed name here.
        Gecko_RegisterProfilerThread(name.as_ptr());
    }
}

fn thread_shutdown(_: usize) {
    unsafe {
        Gecko_UnregisterProfilerThread();
        Gecko_SetJemallocThreadLocalArena(false);
    }
}

lazy_static! {
    /// Global thread pool
    pub static ref STYLE_THREAD_POOL: StyleThreadPool = {
        let stylo_threads = env::var("STYLO_THREADS")
            .map(|s| s.parse::<usize>().expect("invalid STYLO_THREADS value"));
        let mut num_threads = match stylo_threads {
            Ok(num) => num,
            _ => cmp::max(num_cpus::get() * 3 / 4, 1),
        };

        // If num_threads is one, there's no point in creating a thread pool, so
        // force it to zero.
        //
        // We allow developers to force a one-thread pool for testing via a
        // special environmental variable.
        if num_threads == 1 {
            let force_pool = env::var("FORCE_STYLO_THREAD_POOL")
                .ok().map_or(false, |s| s.parse::<usize>().expect("invalid FORCE_STYLO_THREAD_POOL value") == 1);
            if !force_pool {
                num_threads = 0;
            }
        }

        let pool = if num_threads < 1 {
            None
        } else {
            let workers = rayon::ThreadPoolBuilder::new()
                .num_threads(num_threads)
                // Enable a breadth-first rayon traversal. This causes the work
                // queue to be always FIFO, rather than FIFO for stealers and
                // FILO for the owner (which is what rayon does by default). This
                // ensures that we process all the elements at a given depth before
                // proceeding to the next depth, which is important for style sharing.
                .breadth_first()
                .thread_name(thread_name)
                .start_handler(thread_startup)
                .exit_handler(thread_shutdown)
                .stack_size(STYLE_THREAD_STACK_SIZE_KB * 1024)
                .build();
            workers.ok()
        };

        StyleThreadPool {
            num_threads: num_threads,
            style_thread_pool: pool,
        }
    };
    /// Global style data
    pub static ref GLOBAL_STYLE_DATA: GlobalStyleData = GlobalStyleData {
        shared_lock: SharedRwLock::new(),
        options: StyleSystemOptions::default(),
    };
}
<commit_msg>style: Cap the number of style threads at six.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Global style data

use context::StyleSystemOptions;
use gecko_bindings::bindings::{Gecko_RegisterProfilerThread, Gecko_UnregisterProfilerThread};
use gecko_bindings::bindings::Gecko_SetJemallocThreadLocalArena;
use num_cpus;
use parallel::STYLE_THREAD_STACK_SIZE_KB;
use rayon;
use shared_lock::SharedRwLock;
use std::cmp;
use std::env;
use std::ffi::CString;
use thread_state;

/// Global style data
pub struct GlobalStyleData {
    /// Shared RWLock for CSSOM objects
    pub shared_lock: SharedRwLock,

    /// Global style system options determined by env vars.
    pub options: StyleSystemOptions,
}

/// Global thread pool
pub struct StyleThreadPool {
    /// How many threads parallel styling can use.
    pub num_threads: usize,

    /// The parallel styling thread pool.
    pub style_thread_pool: Option<rayon::ThreadPool>,
}

fn thread_name(index: usize) -> String {
    format!("StyleThread#{}", index)
}

fn thread_startup(index: usize) {
    thread_state::initialize_layout_worker_thread();
    unsafe {
        Gecko_SetJemallocThreadLocalArena(true);
    }
    let name = thread_name(index);
    let name = CString::new(name).unwrap();
    unsafe {
        // Gecko_RegisterProfilerThread copies the passed name here.
        Gecko_RegisterProfilerThread(name.as_ptr());
    }
}

fn thread_shutdown(_: usize) {
    unsafe {
        Gecko_UnregisterProfilerThread();
        Gecko_SetJemallocThreadLocalArena(false);
    }
}

lazy_static! {
    /// Global thread pool
    pub static ref STYLE_THREAD_POOL: StyleThreadPool = {
        let stylo_threads = env::var("STYLO_THREADS")
            .map(|s| s.parse::<usize>().expect("invalid STYLO_THREADS value"));
        let mut num_threads = match stylo_threads {
            Ok(num) => num,
            // The default heuristic is num_virtual_cores * .75. This gives us
            // three threads on a hyper-threaded dual core, and six threads on
            // a hyper-threaded quad core. The performance benefit of additional
            // threads seems to level off at around six, so we cap it there on
            // many-core machines (see bug 1431285 comment 14).
            _ => cmp::min(cmp::max(num_cpus::get() * 3 / 4, 1), 6),
        };

        // If num_threads is one, there's no point in creating a thread pool, so
        // force it to zero.
        //
        // We allow developers to force a one-thread pool for testing via a
        // special environmental variable.
        if num_threads == 1 {
            let force_pool = env::var("FORCE_STYLO_THREAD_POOL")
                .ok().map_or(false, |s| s.parse::<usize>().expect("invalid FORCE_STYLO_THREAD_POOL value") == 1);
            if !force_pool {
                num_threads = 0;
            }
        }

        let pool = if num_threads < 1 {
            None
        } else {
            let workers = rayon::ThreadPoolBuilder::new()
                .num_threads(num_threads)
                // Enable a breadth-first rayon traversal. This causes the work
                // queue to be always FIFO, rather than FIFO for stealers and
                // FILO for the owner (which is what rayon does by default). This
                // ensures that we process all the elements at a given depth before
                // proceeding to the next depth, which is important for style sharing.
                .breadth_first()
                .thread_name(thread_name)
                .start_handler(thread_startup)
                .exit_handler(thread_shutdown)
                .stack_size(STYLE_THREAD_STACK_SIZE_KB * 1024)
                .build();
            workers.ok()
        };

        StyleThreadPool {
            num_threads: num_threads,
            style_thread_pool: pool,
        }
    };
    /// Global style data
    pub static ref GLOBAL_STYLE_DATA: GlobalStyleData = GlobalStyleData {
        shared_lock: SharedRwLock::new(),
        options: StyleSystemOptions::default(),
    };
}
<|endoftext|>


<commit_before>use std::io::Read;

use rustc_serialize::json::Json;

use search::mapping;
use system::System;

use api::persistent;
use api::iron::prelude::*;
use api::iron::status;
use api::router::Router;
use api::utils::json_response;

pub fn view_put_mapping(req: &mut Request) -> IronResult<Response> {
    let ref system = get_system!(req);
    let ref index_name = read_path_parameter!(req, "index").unwrap_or("");
    let ref mapping_name = read_path_parameter!(req, "mapping").unwrap_or("");

    // Lock index array
    let mut indices = system.indices.write().unwrap();

    // Get index
    let mut index = get_index_or_404_mut!(indices, *index_name);

    // Load data from body
    let data = json_from_request_body!(req);

    let data = match data {
        Some(data) => data,
        None => {
            // TODO: Better error
            return Ok(json_response(status::BadRequest, "{\"acknowledged\": false}"));
        }
    };

    let data = data.as_object().unwrap().get(*mapping_name).unwrap();

    // Insert mapping
    let mapping = mapping::Mapping::from_json(&data);
    debug!("{:#?}", mapping);
    index.mappings.insert(mapping_name.clone().to_owned(), mapping);

    return Ok(json_response(status::Ok, "{\"acknowledged\": true}"));
}
<commit_msg>Added logging for mapping api<commit_after>use std::io::Read;

use rustc_serialize::json::Json;

use search::mapping;
use system::System;

use api::persistent;
use api::iron::prelude::*;
use api::iron::status;
use api::router::Router;
use api::utils::json_response;

pub fn view_put_mapping(req: &mut Request) -> IronResult<Response> {
    let ref system = get_system!(req);
    let ref index_name = read_path_parameter!(req, "index").unwrap_or("");
    let ref mapping_name = read_path_parameter!(req, "mapping").unwrap_or("");

    // Lock index array
    let mut indices = system.indices.write().unwrap();

    // Get index
    let mut index = get_index_or_404_mut!(indices, *index_name);

    // Load data from body
    let data = json_from_request_body!(req);

    let data = match data {
        Some(data) => data,
        None => {
            // TODO: Better error
            return Ok(json_response(status::BadRequest, "{\"acknowledged\": false}"));
        }
    };

    let data = data.as_object().unwrap().get(*mapping_name).unwrap();

    // Insert mapping
    let mapping = mapping::Mapping::from_json(&data);
    debug!("{:#?}", mapping);
    let is_updating = index.mappings.contains_key(*mapping_name);
    index.mappings.insert(mapping_name.clone().to_owned(), mapping);

    if is_updating {
        system.log.info("[api] updated mapping", b!("index" => *index_name, "mapping" => *mapping_name));
    } else {
        system.log.info("[api] created mapping", b!("index" => *index_name, "mapping" => *mapping_name));
    }

    return Ok(json_response(status::Ok, "{\"acknowledged\": true}"));
}
<|endoftext|>


<commit_before>#![feature(link_args)]
#![feature(start)]

extern crate os;
extern crate syscall;

use os::Process;
use syscall::{ErrNum,Result};
use syscall::libc_helpers::{stdin,stdout};

fn read_line() -> Result<String> {
    let mut v = Vec::new();
    loop {
        let mut buf = vec![0; 100];
        let bytes = syscall::read(unsafe { stdin }, &mut buf[..])?;
        if bytes < buf.len() {
            buf.truncate(bytes);
            v.extend(buf);
            break;
        }

        v.extend(buf);
    }

    String::from_utf8(v).map_err(|_| ErrNum::Utf8Error)
}

#[cfg_attr(target_arch = "x86_64", link_args = "-T ../../libsyscall/arch/amd64/link.ld")]
extern {
}

#[start]
#[no_mangle]
pub fn start(_: isize, _: *const *const u8) -> isize {
    let inherit = unsafe { [ stdin, stdout ] };
    loop {
        print!("> ");

        match read_line() {
            Ok(line) => {
                if line == "exit" {
                    return 0;
                } else if line.len() > 0 {
                    Process::spawn(&line, &inherit).unwrap().wait_for_exit().unwrap();
                }
            },

            Err(code) => { return -(code as isize) }
        }
    }
}
<commit_msg>Error handling<commit_after>#![feature(link_args)]
#![feature(start)]

extern crate os;
extern crate syscall;

use os::Process;
use syscall::{ErrNum,Result};
use syscall::libc_helpers::{stdin,stdout};

fn read_line() -> Result<String> {
    let mut v = Vec::new();
    loop {
        let mut buf = vec![0; 100];
        let bytes = syscall::read(unsafe { stdin }, &mut buf[..])?;
        if bytes < buf.len() {
            buf.truncate(bytes);
            v.extend(buf);
            break;
        }

        v.extend(buf);
    }

    String::from_utf8(v).map_err(|_| ErrNum::Utf8Error)
}

fn run() -> Result<()> {
    let inherit = unsafe { [ stdin, stdout ] };
    loop {
        print!("> ");

        let line = read_line()?;
        if line == "exit" {
            return Ok(());
        }

        if line.len() > 0 {
            let run_line = move || -> Result<()> {
                Process::spawn(&line, &inherit)?.wait_for_exit()?;
                Ok(())
            };

            if let Some(num) = run_line().err() {
                println!("{:?}", num);
            }
        }
    }
}

#[cfg_attr(target_arch = "x86_64", link_args = "-T ../../libsyscall/arch/amd64/link.ld")]
extern {
}

#[start]
#[no_mangle]
pub fn start(_: isize, _: *const *const u8) -> isize {
    run().map(|()| 0).unwrap_or_else(|num| -(num as isize))
}
<|endoftext|>


<commit_before>fn basic_number_to_greek(n: u8, tenplus: bool) -> String {
    if n == 0 {
        "0?".to_owned()
    }

    else if n == 1 && !tenplus  { "mono".to_owned() }
    else if n == 1 && tenplus   { "hen".to_owned()  }

    else if n == 2 && !tenplus  { "di".to_owned() }
    else if n == 2 && tenplus   { "do".to_owned() }

    else if n == 20 && !tenplus { "icosa".to_owned() }
    else if n == 20 && tenplus  { "cosa".to_owned()  }

    else if n == 3  { "tri".to_owned() }
    else if n == 4  { "tetra".to_owned() }
    else if n == 5  { "penta".to_owned() }
    else if n == 6  { "hexa".to_owned() }
    else if n == 7  { "hepta".to_owned() }
    else if n == 8  { "octa".to_owned() }
    else if n == 9  { "nona".to_owned() }
    else if n == 10 { "deca".to_owned() }
    else if n == 11 { "undeca".to_owned() }
    else if n == 12 { "dodeca".to_owned() }
    else if n == 30 { "triaconta".to_owned() }

    else {
        n.to_string().to_owned() + " unknown @basic"
    }
}

fn is_vowel(letter: char) -> bool {
    letter == 'a' || letter == 'e' || letter == 'i' || letter == 'o' || letter == 'u'
}

fn last_char(word: &str) -> char {
    word.chars().nth(word.len()-1).unwrap()
}

pub fn number_to_greek(n: u8) -> String {
    if n <= 12 || n == 20 || n == 30 {
        basic_number_to_greek(n, false)
    }

    else if n >= 13 && n < 20 {
        basic_number_to_greek(n - 10, true) + "deca"
    }

    else if n > 20 && n < 30 {
        let prefix = basic_number_to_greek(n - 20, true);
        let suffix = if is_vowel(last_char(&prefix)) { "cosa" } else { "icosa" };

        prefix + suffix
    }

    else if n > 30 && n < 40 {
        basic_number_to_greek(n - 30, true) + "triaconta"
    }

    else if n >= 40 && n < 100 {
        let factor_ten: u8 = n / 10;

        if n == factor_ten*10 {
            return basic_number_to_greek(factor_ten, true) + "conta";
        } else {
            return basic_number_to_greek(n - factor_ten*10, true) + &basic_number_to_greek(factor_ten, true) + "conta";
        }
    }

    else {
        n.to_string().to_owned() + " unknown @pub"
    }
}

pub fn number_to_roman(n: i8) -> String {
    if n < 0 {
        "-".to_owned() + &number_to_roman(-n)
    }

    else if n == 0 { "0".to_owned() }
    else if n == 1 { "I".to_owned() }
    else if n == 2 { "II".to_owned() }
    else if n == 3 { "III".to_owned() }
    else if n == 4 { "IV".to_owned() }
    else if n == 5 { "V".to_owned() }
    else if n == 6 { "VI".to_owned() }
    else if n == 7 { "VII".to_owned() }
    else if n == 8 { "VIII".to_owned() }
    else if n == 9 { "IX".to_owned() }
    else if n == 10 { "X".to_owned() }
    else if n == 11 { "XI".to_owned() }
    else if n == 12 { "XII".to_owned() }
    else if n == 13 { "XIII".to_owned() }
    else if n == 14 { "XIV".to_owned() }
    else if n == 15 { "XV".to_owned() }
    else if n == 16 { "XVI".to_owned() }

    else {
        "?".to_owned()
    }
}

pub fn subscript(n: u8) -> String {
    if n >= 10 {
        return subscript(n / 10) + &subscript(n % 10);
    }

    else if n == 0  { "₀".to_owned() }
    else if n == 1  { "₁".to_owned() }
    else if n == 2  { "₂".to_owned() }
    else if n == 3  { "₃".to_owned() }
    else if n == 4  { "₄".to_owned() }
    else if n == 5  { "₅".to_owned() }
    else if n == 6  { "₆".to_owned() }
    else if n == 7  { "₇".to_owned() }
    else if n == 8  { "₈".to_owned() }
    else if n == 9  { "₉".to_owned() }

    else {
        "?".to_owned()
    }
}
<commit_msg>Panic on failure at naming<commit_after>fn basic_number_to_greek(n: u8, tenplus: bool) -> String {
    if n == 0 {
        "0?".to_owned()
    }

    else if n == 1 && !tenplus  { "mono".to_owned() }
    else if n == 1 && tenplus   { "hen".to_owned()  }

    else if n == 2 && !tenplus  { "di".to_owned() }
    else if n == 2 && tenplus   { "do".to_owned() }

    else if n == 20 && !tenplus { "icosa".to_owned() }
    else if n == 20 && tenplus  { "cosa".to_owned()  }

    else if n == 3  { "tri".to_owned() }
    else if n == 4  { "tetra".to_owned() }
    else if n == 5  { "penta".to_owned() }
    else if n == 6  { "hexa".to_owned() }
    else if n == 7  { "hepta".to_owned() }
    else if n == 8  { "octa".to_owned() }
    else if n == 9  { "nona".to_owned() }
    else if n == 10 { "deca".to_owned() }
    else if n == 11 { "undeca".to_owned() }
    else if n == 12 { "dodeca".to_owned() }
    else if n == 30 { "triaconta".to_owned() }

    else {
        panic!(n.to_string().to_owned() + " uncalculatable");
    }
}

fn is_vowel(letter: char) -> bool {
    letter == 'a' || letter == 'e' || letter == 'i' || letter == 'o' || letter == 'u'
}

fn last_char(word: &str) -> char {
    word.chars().nth(word.len()-1).unwrap()
}

pub fn number_to_greek(n: u8) -> String {
    if n <= 12 || n == 20 || n == 30 {
        basic_number_to_greek(n, false)
    }

    else if n >= 13 && n < 20 {
        basic_number_to_greek(n - 10, true) + "deca"
    }

    else if n > 20 && n < 30 {
        let prefix = basic_number_to_greek(n - 20, true);
        let suffix = if is_vowel(last_char(&prefix)) { "cosa" } else { "icosa" };

        prefix + suffix
    }

    else if n > 30 && n < 40 {
        basic_number_to_greek(n - 30, true) + "triaconta"
    }

    else if n >= 40 && n < 100 {
        let factor_ten: u8 = n / 10;

        if n == factor_ten*10 {
            return basic_number_to_greek(factor_ten, true) + "conta";
        } else {
            return
                basic_number_to_greek(n - factor_ten*10, true) +
                &basic_number_to_greek(factor_ten, true) + "conta";
        }
    }

    else {
        panic!(n.to_string().to_owned() + " uncalculatable");
    }
}

pub fn number_to_roman(n: i8) -> String {
    if n < 0 {
        "-".to_owned() + &number_to_roman(-n)
    }

    else if n == 0 { "0".to_owned() }
    else if n == 1 { "I".to_owned() }
    else if n == 2 { "II".to_owned() }
    else if n == 3 { "III".to_owned() }
    else if n == 4 { "IV".to_owned() }
    else if n == 5 { "V".to_owned() }
    else if n == 6 { "VI".to_owned() }
    else if n == 7 { "VII".to_owned() }
    else if n == 8 { "VIII".to_owned() }
    else if n == 9 { "IX".to_owned() }
    else if n == 10 { "X".to_owned() }
    else if n == 11 { "XI".to_owned() }
    else if n == 12 { "XII".to_owned() }
    else if n == 13 { "XIII".to_owned() }
    else if n == 14 { "XIV".to_owned() }
    else if n == 15 { "XV".to_owned() }
    else if n == 16 { "XVI".to_owned() }

    else {
        panic!(n.to_string().to_owned() + " uncalculatable");
    }
}

pub fn subscript(n: u8) -> String {
    if n >= 10 {
        return subscript(n / 10) + &subscript(n % 10);
    }

    else if n == 0  { "₀".to_owned() }
    else if n == 1  { "₁".to_owned() }
    else if n == 2  { "₂".to_owned() }
    else if n == 3  { "₃".to_owned() }
    else if n == 4  { "₄".to_owned() }
    else if n == 5  { "₅".to_owned() }
    else if n == 6  { "₆".to_owned() }
    else if n == 7  { "₇".to_owned() }
    else if n == 8  { "₈".to_owned() }
    else if n == 9  { "₉".to_owned() }

    else {
        panic!(n.to_string().to_owned() + " uncalculatable");
    }
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

use crate::completion::{
    completion_config::SnippetCap, completion_item::Builder, CompletionContext, CompletionItem,
    CompletionItemKind, CompletionKind, Completions,
};

fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder {
    CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), label)
        .insert_snippet(cap, snippet)
        .kind(CompletionItemKind::Snippet)
}

pub(super) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) {
    if !(ctx.is_trivial_path && ctx.function_syntax.is_some()) {
        return;
    }
    let cap = match ctx.config.snippet_cap {
        Some(it) => it,
        None => return,
    };

    snippet(ctx, cap, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
    snippet(ctx, cap, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
}

pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) {
    if !ctx.is_new_item {
        return;
    }
    let cap = match ctx.config.snippet_cap {
        Some(it) => it,
        None => return,
    };

    snippet(
        ctx,
        cap,
        "Test module",
        "\
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn ${1:test_name}() {
        $0
    }
}",
    )
    .lookup_by("tmod")
    .add_to(acc);

    snippet(
        ctx,
        cap,
        "Test function",
        "\
#[test]
fn ${1:feature}() {
    $0
}",
    )
    .lookup_by("tfn")
    .add_to(acc);

    snippet(ctx, cap, "macro_rules", "macro_rules! $1 {\n\t($2) => {\n\t\t$0\n\t};\n}").add_to(acc);
    snippet(ctx, cap, "pub(crate)", "pub(crate) $0").add_to(acc);
}

#[cfg(test)]
mod tests {
    use expect::{expect, Expect};

    use crate::completion::{test_utils::completion_list, CompletionKind};

    fn check(ra_fixture: &str, expect: Expect) {
        let actual = completion_list(ra_fixture, CompletionKind::Snippet);
        expect.assert_eq(&actual)
    }

    #[test]
    fn completes_snippets_in_expressions() {
        check(
            r#"fn foo(x: i32) { <|> }"#,
            expect![[r#"
                sn pd
                sn ppd
            "#]],
        );
    }

    #[test]
    fn should_not_complete_snippets_in_path() {
        check(r#"fn foo(x: i32) { ::foo<|> }"#, expect![[""]]);
        check(r#"fn foo(x: i32) { ::<|> }"#, expect![[""]]);
    }

    #[test]
    fn completes_snippets_in_items() {
        check(
            r#"
#[cfg(test)]
mod tests {
    <|>
}
"#,
            expect![[r#"
                sn Test function
                sn Test module
                sn macro_rules
                sn pub(crate)
            "#]],
        )
    }
}
<commit_msg>Display snippet in the completion label<commit_after>//! FIXME: write short doc here

use crate::completion::{
    completion_config::SnippetCap, completion_item::Builder, CompletionContext, CompletionItem,
    CompletionItemKind, CompletionKind, Completions,
};

fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder {
    CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), label)
        .insert_snippet(cap, snippet)
        .kind(CompletionItemKind::Snippet)
}

pub(super) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) {
    if !(ctx.is_trivial_path && ctx.function_syntax.is_some()) {
        return;
    }
    let cap = match ctx.config.snippet_cap {
        Some(it) => it,
        None => return,
    };

    snippet(ctx, cap, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
    snippet(ctx, cap, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
}

pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) {
    if !ctx.is_new_item {
        return;
    }
    let cap = match ctx.config.snippet_cap {
        Some(it) => it,
        None => return,
    };

    snippet(
        ctx,
        cap,
        "tmod (Test module)",
        "\
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn ${1:test_name}() {
        $0
    }
}",
    )
    .lookup_by("tmod")
    .add_to(acc);

    snippet(
        ctx,
        cap,
        "tfn (Test function)",
        "\
#[test]
fn ${1:feature}() {
    $0
}",
    )
    .lookup_by("tfn")
    .add_to(acc);

    snippet(ctx, cap, "macro_rules", "macro_rules! $1 {\n\t($2) => {\n\t\t$0\n\t};\n}").add_to(acc);
    snippet(ctx, cap, "pub(crate)", "pub(crate) $0").add_to(acc);
}

#[cfg(test)]
mod tests {
    use expect::{expect, Expect};

    use crate::completion::{test_utils::completion_list, CompletionKind};

    fn check(ra_fixture: &str, expect: Expect) {
        let actual = completion_list(ra_fixture, CompletionKind::Snippet);
        expect.assert_eq(&actual)
    }

    #[test]
    fn completes_snippets_in_expressions() {
        check(
            r#"fn foo(x: i32) { <|> }"#,
            expect![[r#"
                sn pd
                sn ppd
            "#]],
        );
    }

    #[test]
    fn should_not_complete_snippets_in_path() {
        check(r#"fn foo(x: i32) { ::foo<|> }"#, expect![[""]]);
        check(r#"fn foo(x: i32) { ::<|> }"#, expect![[""]]);
    }

    #[test]
    fn completes_snippets_in_items() {
        check(
            r#"
#[cfg(test)]
mod tests {
    <|>
}
"#,
            expect![[r#"
                sn macro_rules
                sn pub(crate)
                sn tfn (Test function)
                sn tmod (Test module)
            "#]],
        )
    }
}
<|endoftext|>


<commit_before>// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::rc::Rc;
use std::sync::Arc;

use anyhow::{anyhow, bail, Context};
use argh::FromArgs;
use base::{warn, Event};
use cros_async::{sync::Mutex as AsyncMutex, EventAsync, Executor};
use data_model::DataInit;
use futures::channel::mpsc;
use futures::future::{AbortHandle, Abortable};
use hypervisor::ProtectionType;
use once_cell::sync::OnceCell;
use sync::Mutex;
use vm_memory::GuestMemory;
use vmm_vhost::connection::socket::{Endpoint as SocketEndpoint, Listener as SocketListener};
use vmm_vhost::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};

use crate::virtio::snd::cras_backend::{
    async_funcs::{handle_ctrl_queue, handle_pcm_queue, send_pcm_response_worker},
    hardcoded_snd_data, hardcoded_virtio_snd_config, Parameters, PcmResponse, SndData, StreamInfo,
    MAX_QUEUE_NUM, MAX_VRING_LEN,
};
use crate::virtio::snd::layout::virtio_snd_config;
use crate::virtio::vhost::user::device::{
    handler::{sys::Doorbell, DeviceRequestHandler, VhostUserBackend},
    listener::{sys::VhostUserListener, VhostUserListenerTrait},
};
use crate::virtio::{self, copy_config};

static SND_EXECUTOR: OnceCell<Executor> = OnceCell::new();

// Async workers:
// 0 - ctrl
// 1 - event
// 2 - tx
// 3 - rx
const PCM_RESPONSE_WORKER_IDX_OFFSET: usize = 2;
struct CrasSndBackend {
    cfg: virtio_snd_config,
    avail_features: u64,
    acked_features: u64,
    acked_protocol_features: VhostUserProtocolFeatures,
    workers: [Option<AbortHandle>; MAX_QUEUE_NUM],
    response_workers: [Option<AbortHandle>; 2], // tx and rx
    snd_data: Rc<SndData>,
    streams: Rc<AsyncMutex<Vec<AsyncMutex<StreamInfo<'static>>>>>,
    params: Parameters,
    tx_send: mpsc::UnboundedSender<PcmResponse>,
    rx_send: mpsc::UnboundedSender<PcmResponse>,
    tx_recv: Option<mpsc::UnboundedReceiver<PcmResponse>>,
    rx_recv: Option<mpsc::UnboundedReceiver<PcmResponse>>,
}

impl CrasSndBackend {
    pub fn new(params: Parameters) -> anyhow::Result<Self> {
        let cfg = hardcoded_virtio_snd_config(&params);
        let avail_features = virtio::base_features(ProtectionType::Unprotected)
            | VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();

        let snd_data = hardcoded_snd_data(&params);

        let mut streams: Vec<AsyncMutex<StreamInfo>> = Vec::new();
        streams.resize_with(snd_data.pcm_info_len(), Default::default);
        let streams = Rc::new(AsyncMutex::new(streams));

        let (tx_send, tx_recv) = mpsc::unbounded();
        let (rx_send, rx_recv) = mpsc::unbounded();

        Ok(CrasSndBackend {
            cfg,
            avail_features,
            acked_features: 0,
            acked_protocol_features: VhostUserProtocolFeatures::empty(),
            workers: Default::default(),
            response_workers: Default::default(),
            snd_data: Rc::new(snd_data),
            streams,
            params,
            tx_send,
            rx_send,
            tx_recv: Some(tx_recv),
            rx_recv: Some(rx_recv),
        })
    }
}

impl VhostUserBackend for CrasSndBackend {
    fn max_queue_num(&self) -> usize {
        return MAX_QUEUE_NUM;
    }

    fn max_vring_len(&self) -> u16 {
        return MAX_VRING_LEN;
    }

    fn features(&self) -> u64 {
        self.avail_features
    }

    fn ack_features(&mut self, value: u64) -> anyhow::Result<()> {
        let unrequested_features = value & !self.avail_features;
        if unrequested_features != 0 {
            bail!("invalid features are given: {:#x}", unrequested_features);
        }

        self.acked_features |= value;

        Ok(())
    }

    fn acked_features(&self) -> u64 {
        self.acked_features
    }

    fn protocol_features(&self) -> VhostUserProtocolFeatures {
        VhostUserProtocolFeatures::CONFIG | VhostUserProtocolFeatures::MQ
    }

    fn ack_protocol_features(&mut self, features: u64) -> anyhow::Result<()> {
        let features = VhostUserProtocolFeatures::from_bits(features)
            .ok_or_else(|| anyhow!("invalid protocol features are given: {:#x}", features))?;
        let supported = self.protocol_features();
        self.acked_protocol_features = features & supported;
        Ok(())
    }

    fn acked_protocol_features(&self) -> u64 {
        self.acked_protocol_features.bits()
    }

    fn read_config(&self, offset: u64, data: &mut [u8]) {
        copy_config(data, 0, self.cfg.as_slice(), offset)
    }

    fn reset(&mut self) {
        for handle in self.workers.iter_mut().filter_map(Option::take) {
            handle.abort();
        }
    }

    fn start_queue(
        &mut self,
        idx: usize,
        mut queue: virtio::Queue,
        mem: GuestMemory,
        doorbell: Arc<Mutex<Doorbell>>,
        kick_evt: Event,
    ) -> anyhow::Result<()> {
        if let Some(handle) = self.workers.get_mut(idx).and_then(Option::take) {
            warn!("Starting new queue handler without stopping old handler");
            handle.abort();
        }

        // Safe because the executor is initialized in main() below.
        let ex = SND_EXECUTOR.get().expect("Executor not initialized");

        // Enable any virtqueue features that were negotiated (like VIRTIO_RING_F_EVENT_IDX).
        queue.ack_features(self.acked_features);

        let kick_evt =
            EventAsync::new(kick_evt, ex).context("failed to create EventAsync for kick_evt")?;
        let (handle, registration) = AbortHandle::new_pair();
        match idx {
            0 => {
                // ctrl queue
                let streams = self.streams.clone();
                let snd_data = self.snd_data.clone();
                let tx_send = self.tx_send.clone();
                let rx_send = self.rx_send.clone();
                let params = self.params.clone();
                ex.spawn_local(Abortable::new(
                    async move {
                        handle_ctrl_queue(
                            &ex, &mem, &streams, &*snd_data, queue, kick_evt, &doorbell, tx_send,
                            rx_send, &params,
                        )
                        .await
                    },
                    registration,
                ))
                .detach();
            }
            1 => {} // TODO(woodychow): Add event queue support
            2 | 3 => {
                let (send, recv) = if idx == 2 {
                    (self.tx_send.clone(), self.tx_recv.take())
                } else {
                    (self.rx_send.clone(), self.rx_recv.take())
                };
                let mut recv = recv.ok_or_else(|| anyhow!("queue restart is not supported"))?;
                let queue = Rc::new(AsyncMutex::new(queue));
                let queue2 = Rc::clone(&queue);
                let mem = Rc::new(mem);
                let mem2 = Rc::clone(&mem);
                let streams = Rc::clone(&self.streams);
                ex.spawn_local(Abortable::new(
                    async move { handle_pcm_queue(&*mem, &streams, send, &queue, kick_evt).await },
                    registration,
                ))
                .detach();

                let (handle2, registration2) = AbortHandle::new_pair();

                ex.spawn_local(Abortable::new(
                    async move {
                        send_pcm_response_worker(&*mem2, &queue2, &doorbell, &mut recv).await
                    },
                    registration2,
                ))
                .detach();

                self.response_workers[idx - PCM_RESPONSE_WORKER_IDX_OFFSET] = Some(handle2);
            }
            _ => bail!("attempted to start unknown queue: {}", idx),
        }

        self.workers[idx] = Some(handle);
        Ok(())
    }

    fn stop_queue(&mut self, idx: usize) {
        if let Some(handle) = self.workers.get_mut(idx).and_then(Option::take) {
            handle.abort();
        }
        if idx == 2 || idx == 3 {
            if let Some(handle) = self
                .response_workers
                .get_mut(idx - PCM_RESPONSE_WORKER_IDX_OFFSET)
                .and_then(Option::take)
            {
                handle.abort();
            }
        }
    }
}

#[derive(FromArgs)]
#[argh(subcommand, name = "cras-snd")]
/// CRAS device
pub struct Options {
    #[argh(option, arg_name = "PATH")]
    /// path to a socket
    socket: String,
    #[argh(option, arg_name = "CONFIG")]
    /// comma separated key=value pairs for setting up cras snd devices.
    /// Possible key values:
    /// capture - Enable audio capture. Default to false.
    /// client_type - Set specific client type for cras backend.
    /// num_output_devices - Set number of output PCM devices.
    /// num_input_devices - Set number of input PCM devices.
    /// num_output_streams - Set number of output PCM streams per device.
    /// num_input_streams - Set number of input PCM streams per device.
    /// Example: [capture=true,client=crosvm,socket=unified,
    /// num_output_devices=1,num_input_devices=1,num_output_streams=1,num_input_streams=1]
    config: Option<String>,
}

/// Starts a vhost-user snd device with the cras backend.
/// Returns an error if the given `args` is invalid or the device fails to run.
pub fn run_cras_snd_device(opts: Options) -> anyhow::Result<()> {
    let params = opts
        .config
        .unwrap_or("".to_string())
        .parse::<Parameters>()?;

    let snd_device = Box::new(CrasSndBackend::new(params)?);

    // Child, we can continue by spawning the executor and set up the device
    let ex = Executor::new().context("Failed to create executor")?;

    let _ = SND_EXECUTOR.set(ex.clone());

    let listener = VhostUserListener::new_socket(&socket, None);
    // run_until() returns an Result<Result<..>> which the ? operator lets us flatten.
    ex.run_until(listener.run_backend(snd_device, &ex))?
}
<commit_msg>virtio: vhost-user: cras: fix build<commit_after>// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::rc::Rc;
use std::sync::Arc;

use anyhow::{anyhow, bail, Context};
use argh::FromArgs;
use base::{warn, Event};
use cros_async::{sync::Mutex as AsyncMutex, EventAsync, Executor};
use data_model::DataInit;
use futures::channel::mpsc;
use futures::future::{AbortHandle, Abortable};
use hypervisor::ProtectionType;
use once_cell::sync::OnceCell;
use sync::Mutex;
use vm_memory::GuestMemory;
use vmm_vhost::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};

use crate::virtio::snd::cras_backend::{
    async_funcs::{handle_ctrl_queue, handle_pcm_queue, send_pcm_response_worker},
    hardcoded_snd_data, hardcoded_virtio_snd_config, Parameters, PcmResponse, SndData, StreamInfo,
    MAX_QUEUE_NUM, MAX_VRING_LEN,
};
use crate::virtio::snd::layout::virtio_snd_config;
use crate::virtio::vhost::user::device::{
    handler::{sys::Doorbell, VhostUserBackend},
    listener::{sys::VhostUserListener, VhostUserListenerTrait},
};
use crate::virtio::{self, copy_config};

static SND_EXECUTOR: OnceCell<Executor> = OnceCell::new();

// Async workers:
// 0 - ctrl
// 1 - event
// 2 - tx
// 3 - rx
const PCM_RESPONSE_WORKER_IDX_OFFSET: usize = 2;
struct CrasSndBackend {
    cfg: virtio_snd_config,
    avail_features: u64,
    acked_features: u64,
    acked_protocol_features: VhostUserProtocolFeatures,
    workers: [Option<AbortHandle>; MAX_QUEUE_NUM],
    response_workers: [Option<AbortHandle>; 2], // tx and rx
    snd_data: Rc<SndData>,
    streams: Rc<AsyncMutex<Vec<AsyncMutex<StreamInfo<'static>>>>>,
    params: Parameters,
    tx_send: mpsc::UnboundedSender<PcmResponse>,
    rx_send: mpsc::UnboundedSender<PcmResponse>,
    tx_recv: Option<mpsc::UnboundedReceiver<PcmResponse>>,
    rx_recv: Option<mpsc::UnboundedReceiver<PcmResponse>>,
}

impl CrasSndBackend {
    pub fn new(params: Parameters) -> anyhow::Result<Self> {
        let cfg = hardcoded_virtio_snd_config(&params);
        let avail_features = virtio::base_features(ProtectionType::Unprotected)
            | VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();

        let snd_data = hardcoded_snd_data(&params);

        let mut streams: Vec<AsyncMutex<StreamInfo>> = Vec::new();
        streams.resize_with(snd_data.pcm_info_len(), Default::default);
        let streams = Rc::new(AsyncMutex::new(streams));

        let (tx_send, tx_recv) = mpsc::unbounded();
        let (rx_send, rx_recv) = mpsc::unbounded();

        Ok(CrasSndBackend {
            cfg,
            avail_features,
            acked_features: 0,
            acked_protocol_features: VhostUserProtocolFeatures::empty(),
            workers: Default::default(),
            response_workers: Default::default(),
            snd_data: Rc::new(snd_data),
            streams,
            params,
            tx_send,
            rx_send,
            tx_recv: Some(tx_recv),
            rx_recv: Some(rx_recv),
        })
    }
}

impl VhostUserBackend for CrasSndBackend {
    fn max_queue_num(&self) -> usize {
        return MAX_QUEUE_NUM;
    }

    fn max_vring_len(&self) -> u16 {
        return MAX_VRING_LEN;
    }

    fn features(&self) -> u64 {
        self.avail_features
    }

    fn ack_features(&mut self, value: u64) -> anyhow::Result<()> {
        let unrequested_features = value & !self.avail_features;
        if unrequested_features != 0 {
            bail!("invalid features are given: {:#x}", unrequested_features);
        }

        self.acked_features |= value;

        Ok(())
    }

    fn acked_features(&self) -> u64 {
        self.acked_features
    }

    fn protocol_features(&self) -> VhostUserProtocolFeatures {
        VhostUserProtocolFeatures::CONFIG | VhostUserProtocolFeatures::MQ
    }

    fn ack_protocol_features(&mut self, features: u64) -> anyhow::Result<()> {
        let features = VhostUserProtocolFeatures::from_bits(features)
            .ok_or_else(|| anyhow!("invalid protocol features are given: {:#x}", features))?;
        let supported = self.protocol_features();
        self.acked_protocol_features = features & supported;
        Ok(())
    }

    fn acked_protocol_features(&self) -> u64 {
        self.acked_protocol_features.bits()
    }

    fn read_config(&self, offset: u64, data: &mut [u8]) {
        copy_config(data, 0, self.cfg.as_slice(), offset)
    }

    fn reset(&mut self) {
        for handle in self.workers.iter_mut().filter_map(Option::take) {
            handle.abort();
        }
    }

    fn start_queue(
        &mut self,
        idx: usize,
        mut queue: virtio::Queue,
        mem: GuestMemory,
        doorbell: Arc<Mutex<Doorbell>>,
        kick_evt: Event,
    ) -> anyhow::Result<()> {
        if let Some(handle) = self.workers.get_mut(idx).and_then(Option::take) {
            warn!("Starting new queue handler without stopping old handler");
            handle.abort();
        }

        // Safe because the executor is initialized in main() below.
        let ex = SND_EXECUTOR.get().expect("Executor not initialized");

        // Enable any virtqueue features that were negotiated (like VIRTIO_RING_F_EVENT_IDX).
        queue.ack_features(self.acked_features);

        let kick_evt =
            EventAsync::new(kick_evt, ex).context("failed to create EventAsync for kick_evt")?;
        let (handle, registration) = AbortHandle::new_pair();
        match idx {
            0 => {
                // ctrl queue
                let streams = self.streams.clone();
                let snd_data = self.snd_data.clone();
                let tx_send = self.tx_send.clone();
                let rx_send = self.rx_send.clone();
                let params = self.params.clone();
                ex.spawn_local(Abortable::new(
                    async move {
                        handle_ctrl_queue(
                            &ex, &mem, &streams, &*snd_data, queue, kick_evt, &doorbell, tx_send,
                            rx_send, &params,
                        )
                        .await
                    },
                    registration,
                ))
                .detach();
            }
            1 => {} // TODO(woodychow): Add event queue support
            2 | 3 => {
                let (send, recv) = if idx == 2 {
                    (self.tx_send.clone(), self.tx_recv.take())
                } else {
                    (self.rx_send.clone(), self.rx_recv.take())
                };
                let mut recv = recv.ok_or_else(|| anyhow!("queue restart is not supported"))?;
                let queue = Rc::new(AsyncMutex::new(queue));
                let queue2 = Rc::clone(&queue);
                let mem = Rc::new(mem);
                let mem2 = Rc::clone(&mem);
                let streams = Rc::clone(&self.streams);
                ex.spawn_local(Abortable::new(
                    async move { handle_pcm_queue(&*mem, &streams, send, &queue, kick_evt).await },
                    registration,
                ))
                .detach();

                let (handle2, registration2) = AbortHandle::new_pair();

                ex.spawn_local(Abortable::new(
                    async move {
                        send_pcm_response_worker(&*mem2, &queue2, &doorbell, &mut recv).await
                    },
                    registration2,
                ))
                .detach();

                self.response_workers[idx - PCM_RESPONSE_WORKER_IDX_OFFSET] = Some(handle2);
            }
            _ => bail!("attempted to start unknown queue: {}", idx),
        }

        self.workers[idx] = Some(handle);
        Ok(())
    }

    fn stop_queue(&mut self, idx: usize) {
        if let Some(handle) = self.workers.get_mut(idx).and_then(Option::take) {
            handle.abort();
        }
        if idx == 2 || idx == 3 {
            if let Some(handle) = self
                .response_workers
                .get_mut(idx - PCM_RESPONSE_WORKER_IDX_OFFSET)
                .and_then(Option::take)
            {
                handle.abort();
            }
        }
    }
}

#[derive(FromArgs)]
#[argh(subcommand, name = "cras-snd")]
/// CRAS device
pub struct Options {
    #[argh(option, arg_name = "PATH")]
    /// path to a socket
    socket: String,
    #[argh(option, arg_name = "CONFIG")]
    /// comma separated key=value pairs for setting up cras snd devices.
    /// Possible key values:
    /// capture - Enable audio capture. Default to false.
    /// client_type - Set specific client type for cras backend.
    /// num_output_devices - Set number of output PCM devices.
    /// num_input_devices - Set number of input PCM devices.
    /// num_output_streams - Set number of output PCM streams per device.
    /// num_input_streams - Set number of input PCM streams per device.
    /// Example: [capture=true,client=crosvm,socket=unified,
    /// num_output_devices=1,num_input_devices=1,num_output_streams=1,num_input_streams=1]
    config: Option<String>,
}

/// Starts a vhost-user snd device with the cras backend.
/// Returns an error if the given `args` is invalid or the device fails to run.
pub fn run_cras_snd_device(opts: Options) -> anyhow::Result<()> {
    let params = opts
        .config
        .unwrap_or("".to_string())
        .parse::<Parameters>()?;

    let snd_device = Box::new(CrasSndBackend::new(params)?);

    // Child, we can continue by spawning the executor and set up the device
    let ex = Executor::new().context("Failed to create executor")?;

    let _ = SND_EXECUTOR.set(ex.clone());

    let listener = VhostUserListener::new_socket(&opts.socket, None)?;
    // run_until() returns an Result<Result<..>> which the ? operator lets us flatten.
    ex.run_until(listener.run_backend(snd_device, &ex))?
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Write;
use std::str::from_utf8;

use dbutil::normalize_position;
use error::OperationError;
use rdbutil::constants::*;
use rdbutil::{EncodeError, encode_i64, encode_slice_u8};

#[derive(PartialEq, Debug, Clone)]
pub enum ValueString {
    Integer(i64),
    Data(Vec<u8>),
}

impl ValueString {
    pub fn new(newvalue: Vec<u8>) -> Self {
        if newvalue.len() < 32 { // ought to be enough!
            if let Ok(utf8) = from_utf8(&*newvalue) {
                if let Ok(i) = utf8.parse::<i64>() {
                    return ValueString::Integer(i);
                }
            }
        }
        return ValueString::Data(newvalue);
    }

    pub fn to_vec(&self) -> Vec<u8> {
        match *self {
            ValueString::Data(ref data) => data.clone(),
            ValueString::Integer(ref int) => format!("{}", int).into_bytes(),
        }
    }

    pub fn strlen(&self) -> usize {
        match *self {
            ValueString::Data(ref data) => data.len(),
            ValueString::Integer(ref int) => format!("{}", int).len(),
        }
    }

    pub fn append(&mut self, newvalue: Vec<u8>) {
        match *self {
            ValueString::Data(ref mut data) => data.extend(newvalue),
            ValueString::Integer(i) => {
                let oldstr = format!("{}", i);
                *self = ValueString::new([oldstr.into_bytes(), newvalue].concat());
            },
        };
    }

    pub fn incr(&mut self, incr: i64) -> Result<i64, OperationError> {
        let val = match *self {
            ValueString::Integer(i) => i,
            ValueString::Data(ref data) => {
                if data.len() > 32 {
                    return Err(OperationError::OverflowError);
                }
                let res = try!(from_utf8(&data));
                try!(res.parse::<i64>())
            },
        };
        let newval = try!(val.checked_add(incr).ok_or(OperationError::OverflowError));
        *self = ValueString::Integer(newval.clone());
        Ok(newval)
    }

    pub fn incrbyfloat(&mut self, incr: f64) -> Result<f64, OperationError> {
        let val = match *self {
            ValueString::Integer(i) => i as f64,
            ValueString::Data(ref data) => {
                if data.len() > 32 {
                    return Err(OperationError::OverflowError);
                }
                let res = try!(from_utf8(&data));
                try!(res.parse::<f64>())
            },
        };
        let newval = val + incr;
        *self = ValueString::Data(format!("{}", newval).into_bytes());
        Ok(newval)
    }

    pub fn getrange(&self, _start: i64, _stop: i64) -> Vec<u8> {
        let s = match *self {
            ValueString::Integer(ref i) => format!("{}", i).into_bytes(),
            ValueString::Data(ref s) => s.clone(),
        };

        let len = s.len();
        let start = match normalize_position(_start, len) {
            Ok(i) => i,
            Err(g) => if !g { 0 } else { return Vec::new(); }
        } as usize;
        let stop = match normalize_position(_stop, len) {
            Ok(i) => i,
            Err(g) => if !g { return Vec::new(); } else { len }
        } as usize;
        let mut v = Vec::with_capacity(stop - start + 1);
        v.extend(s[start..stop + 1].iter());
        v
    }

    pub fn setbit(&mut self, bitoffset: usize, on: bool) -> bool {
        match *self {
            ValueString::Integer(i) => *self = ValueString::Data(format!("{}", i).into_bytes()),
            ValueString::Data(_) => (),
        };
        let mut d = match *self {
            ValueString::Data(ref mut d) => d,
            _ => panic!("Value should be data"),
        };

        let byte = bitoffset >> 3;

        while byte + 1 > d.len() {
            d.push(0);
        }

        let mut byteval = d[byte];
        let bit = 7 - (bitoffset & 0x7);
        let bitval = byteval & (1 << bit);

        byteval &= !(1 << bit);
        byteval |= (if on { 1 } else { 0 } & 0x1) << bit;
        d[byte] = byteval;

        bitval != 0
    }

    pub fn getbit(&self, bitoffset: usize) -> bool {
        let tmp;
        let d = match *self {
            ValueString::Integer(i) => { tmp = format!("{}", i).into_bytes(); &tmp },
            ValueString::Data(ref d) => d,
        };

        let byte = bitoffset >> 3;
        if byte >= d.len() {
            return false;
        }

        let bit = 7 - (bitoffset & 0x7);;
        let bitval = d[byte] & (1 << bit);

        bitval != 0
    }

    pub fn setrange(&mut self, _index: i64, data: Vec<u8>) -> usize {
        match *self {
            ValueString::Integer(i) => *self = ValueString::Data(format!("{}", i).into_bytes()),
            ValueString::Data(_) => (),
        }

        let mut d = match self {
            &mut ValueString::Data(ref mut s) => s,
            _ => panic!("String must be data"),
        };

        let mut index = match normalize_position(_index, d.len()) {
            Ok(i) => i,
            Err(g) => if !g { 0 } else { _index as usize },
        };
        for _ in d.len()..index {
            d.push(0);
        }
        for c in data {
            d.push(c);
            if index < d.len() - 1 {
                d.swap_remove(index);
            }
            index += 1;
        }
        d.len()
    }

    pub fn dump<T: Write>(&self, writer: &mut T) -> io::Result<usize> {
        let mut v = vec![];
        match *self {
            ValueString::Integer(ref i) => match encode_i64(i.clone(), &mut v) {
                Ok(s) => s,
                Err(e) => match e {
                    EncodeError::IOError(e) => return Err(e),
                    EncodeError::OverflowError => try!(encode_slice_u8(&*self.to_vec(), &mut v, false))
                }
            },
            ValueString::Data(ref d) => try!(encode_slice_u8(&*d, &mut v, true)),
        };
        let data = [
            vec![TYPE_STRING],
            v,
            vec![(VERSION & 0xff) as u8],
            vec![((VERSION >> 8) & 0xff) as u8],
        ].concat();
        writer.write(&*data)
    }

    pub fn debug_object(&self) -> String {
        let mut serialized_data = vec![];
        let serialized = self.dump(&mut serialized_data).unwrap();
        let encoding = match *self {
            ValueString::Integer(_) => "int",
            ValueString::Data(_) => "raw",
        };
        format!("Value at:0x0000000000 refcount:1 encoding:{} serializedlength:{} lru:0 lru_seconds_idle:0", encoding, serialized).to_owned()
    }
}

#[cfg(test)]
mod test_rdb {
    use std::i64;

    use super::ValueString;

    #[test]
    fn dump_integer() {
        let mut v = vec![];
        ValueString::Integer(1).dump(&mut v).unwrap();
        assert_eq!(&*v, b"\x00\xc0\x01\x07\x00");
    }

    #[test]
    fn dump_integer_overflow() {
        let mut v = vec![];
        ValueString::Integer(i64::MAX).dump(&mut v).unwrap();
        assert_eq!(&*v, b"\x00\x139223372036854775807\x07\x00");
    }

    #[test]
    fn dump_string() {
        let mut v = vec![];
        ValueString::Data(b"hello world".to_vec()).dump(&mut v).unwrap();
        assert_eq!(&*v, b"\x00\x0bhello world\x07\x00");
    }
}
<commit_msg>Bail SETRANGE with empty argument<commit_after>use std::io;
use std::io::Write;
use std::str::from_utf8;

use dbutil::normalize_position;
use error::OperationError;
use rdbutil::constants::*;
use rdbutil::{EncodeError, encode_i64, encode_slice_u8};

#[derive(PartialEq, Debug, Clone)]
pub enum ValueString {
    Integer(i64),
    Data(Vec<u8>),
}

impl ValueString {
    pub fn new(newvalue: Vec<u8>) -> Self {
        if newvalue.len() < 32 { // ought to be enough!
            if let Ok(utf8) = from_utf8(&*newvalue) {
                if let Ok(i) = utf8.parse::<i64>() {
                    return ValueString::Integer(i);
                }
            }
        }
        return ValueString::Data(newvalue);
    }

    pub fn to_vec(&self) -> Vec<u8> {
        match *self {
            ValueString::Data(ref data) => data.clone(),
            ValueString::Integer(ref int) => format!("{}", int).into_bytes(),
        }
    }

    pub fn strlen(&self) -> usize {
        match *self {
            ValueString::Data(ref data) => data.len(),
            ValueString::Integer(ref int) => format!("{}", int).len(),
        }
    }

    pub fn append(&mut self, newvalue: Vec<u8>) {
        match *self {
            ValueString::Data(ref mut data) => data.extend(newvalue),
            ValueString::Integer(i) => {
                let oldstr = format!("{}", i);
                *self = ValueString::new([oldstr.into_bytes(), newvalue].concat());
            },
        };
    }

    pub fn incr(&mut self, incr: i64) -> Result<i64, OperationError> {
        let val = match *self {
            ValueString::Integer(i) => i,
            ValueString::Data(ref data) => {
                if data.len() > 32 {
                    return Err(OperationError::OverflowError);
                }
                let res = try!(from_utf8(&data));
                try!(res.parse::<i64>())
            },
        };
        let newval = try!(val.checked_add(incr).ok_or(OperationError::OverflowError));
        *self = ValueString::Integer(newval.clone());
        Ok(newval)
    }

    pub fn incrbyfloat(&mut self, incr: f64) -> Result<f64, OperationError> {
        let val = match *self {
            ValueString::Integer(i) => i as f64,
            ValueString::Data(ref data) => {
                if data.len() > 32 {
                    return Err(OperationError::OverflowError);
                }
                let res = try!(from_utf8(&data));
                try!(res.parse::<f64>())
            },
        };
        let newval = val + incr;
        *self = ValueString::Data(format!("{}", newval).into_bytes());
        Ok(newval)
    }

    pub fn getrange(&self, _start: i64, _stop: i64) -> Vec<u8> {
        let s = match *self {
            ValueString::Integer(ref i) => format!("{}", i).into_bytes(),
            ValueString::Data(ref s) => s.clone(),
        };

        let len = s.len();
        let start = match normalize_position(_start, len) {
            Ok(i) => i,
            Err(g) => if !g { 0 } else { return Vec::new(); }
        } as usize;
        let stop = match normalize_position(_stop, len) {
            Ok(i) => i,
            Err(g) => if !g { return Vec::new(); } else { len }
        } as usize;
        let mut v = Vec::with_capacity(stop - start + 1);
        v.extend(s[start..stop + 1].iter());
        v
    }

    pub fn setbit(&mut self, bitoffset: usize, on: bool) -> bool {
        match *self {
            ValueString::Integer(i) => *self = ValueString::Data(format!("{}", i).into_bytes()),
            ValueString::Data(_) => (),
        };
        let mut d = match *self {
            ValueString::Data(ref mut d) => d,
            _ => panic!("Value should be data"),
        };

        let byte = bitoffset >> 3;

        while byte + 1 > d.len() {
            d.push(0);
        }

        let mut byteval = d[byte];
        let bit = 7 - (bitoffset & 0x7);
        let bitval = byteval & (1 << bit);

        byteval &= !(1 << bit);
        byteval |= (if on { 1 } else { 0 } & 0x1) << bit;
        d[byte] = byteval;

        bitval != 0
    }

    pub fn getbit(&self, bitoffset: usize) -> bool {
        let tmp;
        let d = match *self {
            ValueString::Integer(i) => { tmp = format!("{}", i).into_bytes(); &tmp },
            ValueString::Data(ref d) => d,
        };

        let byte = bitoffset >> 3;
        if byte >= d.len() {
            return false;
        }

        let bit = 7 - (bitoffset & 0x7);;
        let bitval = d[byte] & (1 << bit);

        bitval != 0
    }

    pub fn setrange(&mut self, _index: i64, data: Vec<u8>) -> usize {
        if data.len() == 0 {
            return self.strlen();
        }

        match *self {
            ValueString::Integer(i) => *self = ValueString::Data(format!("{}", i).into_bytes()),
            ValueString::Data(_) => (),
        }

        let mut d = match self {
            &mut ValueString::Data(ref mut s) => s,
            _ => panic!("String must be data"),
        };

        let mut index = match normalize_position(_index, d.len()) {
            Ok(i) => i,
            Err(g) => if !g { 0 } else { _index as usize },
        };
        for _ in d.len()..index {
            d.push(0);
        }
        for c in data {
            d.push(c);
            if index < d.len() - 1 {
                d.swap_remove(index);
            }
            index += 1;
        }
        d.len()
    }

    pub fn dump<T: Write>(&self, writer: &mut T) -> io::Result<usize> {
        let mut v = vec![];
        match *self {
            ValueString::Integer(ref i) => match encode_i64(i.clone(), &mut v) {
                Ok(s) => s,
                Err(e) => match e {
                    EncodeError::IOError(e) => return Err(e),
                    EncodeError::OverflowError => try!(encode_slice_u8(&*self.to_vec(), &mut v, false))
                }
            },
            ValueString::Data(ref d) => try!(encode_slice_u8(&*d, &mut v, true)),
        };
        let data = [
            vec![TYPE_STRING],
            v,
            vec![(VERSION & 0xff) as u8],
            vec![((VERSION >> 8) & 0xff) as u8],
        ].concat();
        writer.write(&*data)
    }

    pub fn debug_object(&self) -> String {
        let mut serialized_data = vec![];
        let serialized = self.dump(&mut serialized_data).unwrap();
        let encoding = match *self {
            ValueString::Integer(_) => "int",
            ValueString::Data(_) => "raw",
        };
        format!("Value at:0x0000000000 refcount:1 encoding:{} serializedlength:{} lru:0 lru_seconds_idle:0", encoding, serialized).to_owned()
    }
}

#[cfg(test)]
mod test_rdb {
    use std::i64;

    use super::ValueString;

    #[test]
    fn dump_integer() {
        let mut v = vec![];
        ValueString::Integer(1).dump(&mut v).unwrap();
        assert_eq!(&*v, b"\x00\xc0\x01\x07\x00");
    }

    #[test]
    fn dump_integer_overflow() {
        let mut v = vec![];
        ValueString::Integer(i64::MAX).dump(&mut v).unwrap();
        assert_eq!(&*v, b"\x00\x139223372036854775807\x07\x00");
    }

    #[test]
    fn dump_string() {
        let mut v = vec![];
        ValueString::Data(b"hello world".to_vec()).dump(&mut v).unwrap();
        assert_eq!(&*v, b"\x00\x0bhello world\x07\x00");
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::sync::atomic::{self, AtomicPtr};

use local;
use garbage::Garbage;
use guard::Guard;

/// A concurrently accessible and updatable cell.
///
/// This can be compared to `std::cell::RefCell` in some ways: It allows accessing, referencing,
/// updating, etc., however contrary to `RefCell`, this is concurrent and has no aliasing
/// restrictions. It is futher distinguished from `std::sync::AtomicPtr` in that it allows
/// references to the inner data without the ABA problem or any variant thereof.
///
/// It conviniently wraps this crates API in a seemless manner.
pub struct Cell<T> {
    /// The inner atomic pointer.
    inner: AtomicPtr<T>,
}

impl<T> Cell<T> {
    /// Get a reference to the current content of the cell.
    ///
    /// This returns a `Guard<T>`, which "protects" the inner value such that it is not dropped
    /// before the guard is no longer active. This is all handled automatically through RAII.
    ///
    /// The `ordering` defines what constraints the atomic operation has. Refer to the LLVM
    /// documentation for more information.
    pub fn load(&self, ordering: atomic::Ordering) -> Guard<T> {
        // Load the inner and wrap it in a guard.
        Guard::new(|| unsafe { &*self.inner.load(ordering) });
    }

    /// Store a new value in the cell.
    ///
    /// The old value of the cell will eventually be dropped, at some point after all the guarding
    /// references are gone.
    ///
    /// The `ordering` defines what constraints the atomic operation has. Refer to the LLVM
    /// documentation for more information.
    pub fn store(&self, new: Box<T>, ordering: atomic::Ordering) {
        // Swap the contents with the new value.
        let ptr = self.inner.swap(&new, ordering);
        // Queue the deletion of the content.
        local::add_garbage(unsafe { Garbage::new(ptr) });
    }

    /// Swap the old value with a new.
    ///
    /// This returns a `Guard<T>` as readers of the old values might exist. The old value will be
    /// queued for destruction.
    ///
    /// The `ordering` defines what constraints the atomic operation has. Refer to the LLVM
    /// documentation for more information.
    ///
    /// # Performance
    ///
    /// This is slower than `store` as it requires initializing a new guard, which requires at
    /// least two atomic operations. Thus, when possible, you should use `store`.
    pub fn swap(&self, new: Box<T>, ordering: atomic::Ordering) -> Guard<T> {
        // Create the guard. It is very important that this is done before the garbage is added,
        // otherwise we might introduce premature frees.
        let guard = Guard::new(|| {
            // Swap the atomic pointer with the new one.
            unsafe { &*self.inner.swap(new, ordering) }
        });

        // Since the pointer is now unreachable from the cell, it can safely be queued for
        // deletion.
        local::add_garbage(Garbage::new(&guard));

        guard
    }

    /// Swap a value if it matches.
    ///
    /// This compares `self` to `old`. If they match, it is swapped with `new` and a guard to the
    /// old value is returned wrapped in `Ok`. If not, a tuple containing the guard to the actual
    /// (non-matching) value and the box of `new` — wrapped in `Err` — is returned.
    ///
    /// The `ordering` defines what constraints the atomic operation has. Refer to the LLVM
    /// documentation for more information.
    ///
    /// # Performance
    ///
    /// This is slower than `compare_and_set` as it requires initializing a new guard, which
    /// requires at least two atomic operations. Thus, when possible, you should use
    /// `compare_and_set`.
    pub fn compare_and_swap(&self, old: &T, new: Box<T>, ordering: atomic::Ordering)
    -> Result<Guard<T>, (Guard<T>, Box<T>)> {
        // Create the guard beforehand to avoid premature frees.
        let guard = Guard::new(|| {
            // The guard is active, so we can do the CAS now.
            unsafe { &*self.inner.compare_and_swap(old, &new, ordering) }
        });

        // Check if the CAS was successful.
        if guard == old {
            // It was. `self` is now `new`.

            // This is critical for avoiding premature drop as the pointer to the box is stored in
            // `self.inner` now.
            mem::forget(new);

            // Queue the now-unreachable garbage of `old`.
            local::add_garbage(Garbage::new(old));

            Ok(guard)
        } else {
            // It failed.
            Err((guard, new))
        }
    }
}
<commit_msg>Add `compare_and_set` to `concurrent::Cell`<commit_after>use std::mem;
use std::sync::atomic::{self, AtomicPtr};

use local;
use garbage::Garbage;
use guard::Guard;

/// A concurrently accessible and updatable cell.
///
/// This can be compared to `std::cell::RefCell` in some ways: It allows accessing, referencing,
/// updating, etc., however contrary to `RefCell`, this is concurrent and has no aliasing
/// restrictions. It is futher distinguished from `std::sync::AtomicPtr` in that it allows
/// references to the inner data without the ABA problem or any variant thereof.
///
/// It conviniently wraps this crates API in a seemless manner.
pub struct Cell<T> {
    /// The inner atomic pointer.
    inner: AtomicPtr<T>,
}

impl<T> Cell<T> {
    /// Get a reference to the current content of the cell.
    ///
    /// This returns a `Guard<T>`, which "protects" the inner value such that it is not dropped
    /// before the guard is no longer active. This is all handled automatically through RAII.
    ///
    /// The `ordering` defines what constraints the atomic operation has. Refer to the LLVM
    /// documentation for more information.
    pub fn load(&self, ordering: atomic::Ordering) -> Guard<T> {
        // Load the inner and wrap it in a guard.
        Guard::new(|| unsafe { &*self.inner.load(ordering) });
    }

    /// Store a new value in the cell.
    ///
    /// The old value of the cell will eventually be dropped, at some point after all the guarding
    /// references are gone.
    ///
    /// The `ordering` defines what constraints the atomic operation has. Refer to the LLVM
    /// documentation for more information.
    pub fn store(&self, new: Box<T>, ordering: atomic::Ordering) {
        // Swap the contents with the new value.
        let ptr = self.inner.swap(&new, ordering);
        // Queue the deletion of the content.
        local::add_garbage(unsafe { Garbage::new(ptr) });
    }

    /// Swap the old value with a new.
    ///
    /// This returns a `Guard<T>` as readers of the old values might exist. The old value will be
    /// queued for destruction.
    ///
    /// The `ordering` defines what constraints the atomic operation has. Refer to the LLVM
    /// documentation for more information.
    ///
    /// # Performance
    ///
    /// This is slower than `store` as it requires initializing a new guard, which requires at
    /// least two atomic operations. Thus, when possible, you should use `store`.
    pub fn swap(&self, new: Box<T>, ordering: atomic::Ordering) -> Guard<T> {
        // Create the guard. It is very important that this is done before the garbage is added,
        // otherwise we might introduce premature frees.
        let guard = Guard::new(|| {
            // Swap the atomic pointer with the new one.
            unsafe { &*self.inner.swap(new, ordering) }
        });

        // Since the pointer is now unreachable from the cell, it can safely be queued for
        // deletion.
        local::add_garbage(Garbage::new(&guard));

        guard
    }

    /// Set a value if it matches.
    ///
    /// This compares `self` to `old`. If they match, the value is set to `new` and `Ok(())` is
    /// returned. Otherwise, `Err(new)` is returned.
    ///
    /// The `ordering` defines what constraints the atomic operation has. Refer to the LLVM
    /// documentation for more information.
    pub fn compare_and_set(&self, old: &T, new: Box<T>, ordering: atomic::Ordering)
    -> Result<(), Box<T>)> {
        // Compare-and-swap the value.
        let ptr = self.inner.compare_and_swap(old, &new, ordering);

        // Check if the CAS was successful.
        if ptr == old {
            // It was. `self` is now `new`.

            // This is critical for avoiding premature drop as the pointer to the box is stored in
            // `self.inner` now.
            mem::forget(new);

            // Queue the now-unreachable garbage of `old`.
            local::add_garbage(Garbage::new(old));

            Ok()
        } else {
            // It failed.
            Err(new)
        }
    }

    /// Swap a value if it matches.
    ///
    /// This compares `self` to `old`. If they match, it is swapped with `new` and a guard to the
    /// old value is returned wrapped in `Ok`. If not, a tuple containing the guard to the actual
    /// (non-matching) value and the box of `new` — wrapped in `Err` — is returned.
    ///
    /// The `ordering` defines what constraints the atomic operation has. Refer to the LLVM
    /// documentation for more information.
    ///
    /// # Performance
    ///
    /// This is slower than `compare_and_set` as it requires initializing a new guard, which
    /// requires at least two atomic operations. Thus, when possible, you should use
    /// `compare_and_set`.
    pub fn compare_and_swap(&self, old: &T, new: Box<T>, ordering: atomic::Ordering)
    -> Result<Guard<T>, (Guard<T>, Box<T>)> {
        // Create the guard beforehand to avoid premature frees.
        let guard = Guard::new(|| {
            // The guard is active, so we can do the CAS now.
            unsafe { &*self.inner.compare_and_swap(old, &new, ordering) }
        });

        // Check if the CAS was successful.
        if guard == old {
            // It was. `self` is now `new`.

            // This is critical for avoiding premature drop as the pointer to the box is stored in
            // `self.inner` now.
            mem::forget(new);

            // Queue the now-unreachable garbage of `old`.
            local::add_garbage(Garbage::new(old));

            Ok(guard)
        } else {
            // It failed.
            Err((guard, new))
        }
    }
}
<|endoftext|>


<commit_before>use std::cmp::{Ord, Ordering};
use std::fmt;
use uuid::Uuid;

#[cfg(test)]
use once_cell::sync::Lazy;
#[cfg(test)]
use std::sync::atomic;

/// Uuid identifying a segment.
///
/// Tantivy's segment are identified
/// by a UUID which is used to prefix the filenames
/// of all of the file associated with the segment.
///
/// In unit test, for reproducability, the `SegmentId` are
/// simply generated in an autoincrement fashion.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct SegmentId(Uuid);

#[cfg(test)]
static AUTO_INC_COUNTER: Lazy<atomic::AtomicUsize> = Lazy::new(|| atomic::AtomicUsize::default());

#[cfg(test)]
const ZERO_ARRAY: [u8; 8] = [0u8; 8];

// During tests, we generate the segment id in a autoincrement manner
// for consistency of segment id between run.
//
// The order of the test execution is not guaranteed, but the order
// of segments within a single test is guaranteed.
#[cfg(test)]
fn create_uuid() -> Uuid {
    let new_auto_inc_id = (*AUTO_INC_COUNTER).fetch_add(1, atomic::Ordering::SeqCst);
    Uuid::from_fields(new_auto_inc_id as u32, 0, 0, &ZERO_ARRAY).unwrap()
}

#[cfg(not(test))]
fn create_uuid() -> Uuid {
    Uuid::new_v4()
}

impl SegmentId {
    #[doc(hidden)]
    pub fn generate_random() -> SegmentId {
        SegmentId(create_uuid())
    }

    /// Returns a shorter identifier of the segment.
    ///
    /// We are using UUID4, so only 6 bits are fixed,
    /// and the rest is random.
    ///
    /// Picking the first 8 chars is ok to identify
    /// segments in a display message.
    pub fn short_uuid_string(&self) -> String {
        (&self.0.to_simple_ref().to_string()[..8]).to_string()
    }

    /// Returns a segment uuid string.
    pub fn uuid_string(&self) -> String {
        self.0.to_simple_ref().to_string()
    }
}

impl fmt::Debug for SegmentId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Seg({:?})", self.short_uuid_string())
    }
}

impl PartialOrd for SegmentId {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for SegmentId {
    fn cmp(&self, other: &Self) -> Ordering {
        self.0.as_bytes().cmp(other.0.as_bytes())
    }
}
<commit_msg>Added segmentid_from_string (#636)<commit_after>use std::cmp::{Ord, Ordering};
use std::fmt;
use uuid::Uuid;

#[cfg(test)]
use once_cell::sync::Lazy;
use std::error::Error;
use std::str::FromStr;
#[cfg(test)]
use std::sync::atomic;

/// Uuid identifying a segment.
///
/// Tantivy's segment are identified
/// by a UUID which is used to prefix the filenames
/// of all of the file associated with the segment.
///
/// In unit test, for reproducability, the `SegmentId` are
/// simply generated in an autoincrement fashion.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct SegmentId(Uuid);

#[cfg(test)]
static AUTO_INC_COUNTER: Lazy<atomic::AtomicUsize> = Lazy::new(|| atomic::AtomicUsize::default());

#[cfg(test)]
const ZERO_ARRAY: [u8; 8] = [0u8; 8];

// During tests, we generate the segment id in a autoincrement manner
// for consistency of segment id between run.
//
// The order of the test execution is not guaranteed, but the order
// of segments within a single test is guaranteed.
#[cfg(test)]
fn create_uuid() -> Uuid {
    let new_auto_inc_id = (*AUTO_INC_COUNTER).fetch_add(1, atomic::Ordering::SeqCst);
    Uuid::from_fields(new_auto_inc_id as u32, 0, 0, &ZERO_ARRAY).unwrap()
}

#[cfg(not(test))]
fn create_uuid() -> Uuid {
    Uuid::new_v4()
}

impl SegmentId {
    #[doc(hidden)]
    pub fn generate_random() -> SegmentId {
        SegmentId(create_uuid())
    }

    /// Returns a shorter identifier of the segment.
    ///
    /// We are using UUID4, so only 6 bits are fixed,
    /// and the rest is random.
    ///
    /// Picking the first 8 chars is ok to identify
    /// segments in a display message (e.g. a5c4dfcb).
    pub fn short_uuid_string(&self) -> String {
        (&self.0.to_simple_ref().to_string()[..8]).to_string()
    }

    /// Returns a segment uuid string.
    ///
    /// It consists in 32 lowercase hexadecimal chars
    /// (e.g. a5c4dfcbdfe645089129e308e26d5523)
    pub fn uuid_string(&self) -> String {
        self.0.to_simple_ref().to_string()
    }

    /// Build a `SegmentId` string from the full uuid string.
    ///
    /// E.g. "a5c4dfcbdfe645089129e308e26d5523"
    pub fn from_uuid_string(uuid_string: &str) -> Result<SegmentId, SegmentIdParseError> {
        FromStr::from_str(uuid_string)
    }
}

/// Error type used when parsing a `SegmentId` from a string fails.
pub struct SegmentIdParseError(uuid::parser::ParseError);

impl Error for SegmentIdParseError {}

impl fmt::Debug for SegmentIdParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::Display for SegmentIdParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl FromStr for SegmentId {
    type Err = SegmentIdParseError;

    fn from_str(uuid_string: &str) -> Result<Self, SegmentIdParseError> {
        let uuid = Uuid::parse_str(uuid_string).map_err(SegmentIdParseError)?;
        Ok(SegmentId(uuid))
    }
}

impl fmt::Debug for SegmentId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Seg({:?})", self.short_uuid_string())
    }
}

impl PartialOrd for SegmentId {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for SegmentId {
    fn cmp(&self, other: &Self) -> Ordering {
        self.0.as_bytes().cmp(other.0.as_bytes())
    }
}

#[cfg(test)]
mod tests {
    use super::SegmentId;

    #[test]
    fn test_to_uuid_string() {
        let full_uuid = "a5c4dfcbdfe645089129e308e26d5523";
        let segment_id = SegmentId::from_uuid_string(full_uuid).unwrap();
        assert_eq!(segment_id.uuid_string(), full_uuid);
        assert_eq!(segment_id.short_uuid_string(), "a5c4dfcb");
        // one extra char
        assert!(SegmentId::from_uuid_string("a5c4dfcbdfe645089129e308e26d5523b").is_err());
    }
}
<|endoftext|>


<commit_before>mod test;

use std::rc::Rc;
use std::cell::RefCell;

use core::*;
use lexer::*;
use parser::*;
use walker::*;

pub struct Printer {
    vm: Rc<RefCell<Heliqs>>,
}

impl Printer {
    pub fn new(vm: Rc<RefCell<Heliqs>>) -> Self {
        Printer{ vm: vm }
    }

    pub fn print(&self) -> String {
        if let Some(entrypoint) = self.vm.borrow().entry() {
            self.print_aexp(entrypoint, 0)
        } else {
            "".to_string()
        }
    }

    pub fn print_aexp(&self, i: NodeId, nest_level: u32) -> String {
        let vm = self.vm.borrow();
        let &Node(_, ref epiq) = vm.get_epiq(i);
        match **epiq {
            Epiq::Unit => ";".to_string(),
            Epiq::Tval => "^T".to_string(),
            Epiq::Fval => "^F".to_string(),
            Epiq::Name(ref n) => n.to_string(),
            Epiq::Uit8(ref n) => format!("{}", n),
            Epiq::Text(ref n) => format!("\"{}\"", n),
            Epiq::Prim(ref n) => format!("Prim({})", n),
            Epiq::Tpiq { ref o, p, q } => self.print_piq(o, p, q, nest_level),
            Epiq::Mpiq { ref o, p, q } => self.print_piq(o, p, q, nest_level),
            Epiq::Eval(p, q) => self.print_piq(">", p, q, nest_level),
            Epiq::Lpiq(p, q) => self.print_piq(":", p, q, nest_level),
            Epiq::Appl(p, q) => self.print_piq("!", p, q, nest_level),
            Epiq::Rslv(p, q) => self.print_piq("@", p, q, nest_level),
            Epiq::Cond(p, q) => self.print_piq("?", p, q, nest_level),
            Epiq::Envn(p, q) => self.print_piq("%", p, q, nest_level),
            Epiq::Bind(p, q) => self.print_piq("#", p, q, nest_level),
            Epiq::Accs(p, q) => self.print_piq(".", p, q, nest_level),
            Epiq::Lmbd(p, q) => self.print_piq(r"\", p, q, nest_level),

            // _ => "".to_string(),
        }
    }

    fn print_piq(&self, otag: &str, p: NodeId, q:NodeId, nest_level: u32) -> String {
        format!("{}({} {})", otag, self.print_aexp(p, nest_level + 1), self.print_aexp(q, nest_level + 1))
    }
}

pub fn print_str(left: &str, right: &str) {
    let mut iter = left.bytes();
    let scanners: &Vec<&Scanner> = &all_scanners!();
    let lexer = Lexer::new(&mut iter, scanners);

    let vm = Rc::new(RefCell::new(Heliqs::new()));
    let vm2 = vm.clone();
    let mut parser = Parser::new(lexer, vm);
    let _parsed_ast = parser.parse();

    let printer = Printer::new(vm2);

    assert_eq!(printer.print(), right);
}

pub fn evaled_str(left: &str) -> String {
    let mut iter = left.bytes();
    let scanners: &Vec<&Scanner> = &all_scanners!();
    let lexer = Lexer::new(&mut iter, scanners);

    let vm = Rc::new(RefCell::new(Heliqs::new()));
    let vm2 = vm.clone();
    let vm3 = vm.clone();
    let mut parser = Parser::new(lexer, vm);
    parser.parse();

    let walker = Walker::new(vm2);
    walker.walk();

    let printer = Printer::new(vm3);
    printer.print().to_string()
}

pub fn print_evaled_str(left: &str, right: &str) {
    let result = evaled_str(left);
    assert_eq!(result, right);
}

/// leftを評価したらちゃんとrightになるかどうかのテスト
pub fn print_syntax_sugar(left: &str, right: &str) {
    let result_left = evaled_str(left);
    let result_right = evaled_str(right);
    assert_eq!(result_left, result_right);
}

pub fn only_evaluate(s: &str) {
    let mut iter = s.bytes();
    let scanners: &Vec<&Scanner> = &all_scanners!();
    let lexer = Lexer::new(&mut iter, scanners);

    let vm = Rc::new(RefCell::new(Heliqs::new()));
    let vm2 = vm.clone();

    let mut parser = Parser::new(lexer, vm);
    parser.parse();

    let walker = Walker::new(vm2);
    walker.walk();
}

fn craete_vm<'a>() -> Rc<RefCell<Heliqs>> {
    Rc::new(RefCell::new(Heliqs::new()))
}
<commit_msg>change printing letter for Mpiq<commit_after>mod test;

use std::rc::Rc;
use std::cell::RefCell;

use core::*;
use lexer::*;
use parser::*;
use walker::*;

pub struct Printer {
    vm: Rc<RefCell<Heliqs>>,
}

impl Printer {
    pub fn new(vm: Rc<RefCell<Heliqs>>) -> Self {
        Printer{ vm: vm }
    }

    pub fn print(&self) -> String {
        if let Some(entrypoint) = self.vm.borrow().entry() {
            self.print_aexp(entrypoint, 0)
        } else {
            "".to_string()
        }
    }

    pub fn print_aexp(&self, i: NodeId, nest_level: u32) -> String {
        let vm = self.vm.borrow();
        let &Node(_, ref epiq) = vm.get_epiq(i);
        match **epiq {
            Epiq::Unit => ";".to_string(),
            Epiq::Tval => "^T".to_string(),
            Epiq::Fval => "^F".to_string(),
            Epiq::Name(ref n) => n.to_string(),
            Epiq::Uit8(ref n) => format!("{}", n),
            Epiq::Text(ref n) => format!("\"{}\"", n),
            Epiq::Prim(ref n) => format!("Prim({})", n),
            Epiq::Tpiq { ref o, p, q } => self.print_piq(o, p, q, nest_level),
            Epiq::Mpiq { ref o, p, q } => self.print_piq(&format!("^{}", o), p, q, nest_level),
            Epiq::Eval(p, q) => self.print_piq(">", p, q, nest_level),
            Epiq::Lpiq(p, q) => self.print_piq(":", p, q, nest_level),
            Epiq::Appl(p, q) => self.print_piq("!", p, q, nest_level),
            Epiq::Rslv(p, q) => self.print_piq("@", p, q, nest_level),
            Epiq::Cond(p, q) => self.print_piq("?", p, q, nest_level),
            Epiq::Envn(p, q) => self.print_piq("%", p, q, nest_level),
            Epiq::Bind(p, q) => self.print_piq("#", p, q, nest_level),
            Epiq::Accs(p, q) => self.print_piq(".", p, q, nest_level),
            Epiq::Lmbd(p, q) => self.print_piq(r"\", p, q, nest_level),

            // _ => "".to_string(),
        }
    }

    fn print_piq(&self, otag: &str, p: NodeId, q:NodeId, nest_level: u32) -> String {
        format!("{}({} {})", otag, self.print_aexp(p, nest_level + 1), self.print_aexp(q, nest_level + 1))
    }
}

pub fn print_str(left: &str, right: &str) {
    let mut iter = left.bytes();
    let scanners: &Vec<&Scanner> = &all_scanners!();
    let lexer = Lexer::new(&mut iter, scanners);

    let vm = Rc::new(RefCell::new(Heliqs::new()));
    let vm2 = vm.clone();
    let mut parser = Parser::new(lexer, vm);
    let _parsed_ast = parser.parse();

    let printer = Printer::new(vm2);

    assert_eq!(printer.print(), right);
}

pub fn evaled_str(left: &str) -> String {
    let mut iter = left.bytes();
    let scanners: &Vec<&Scanner> = &all_scanners!();
    let lexer = Lexer::new(&mut iter, scanners);

    let vm = Rc::new(RefCell::new(Heliqs::new()));
    let vm2 = vm.clone();
    let vm3 = vm.clone();
    let mut parser = Parser::new(lexer, vm);
    parser.parse();

    let walker = Walker::new(vm2);
    walker.walk();

    let printer = Printer::new(vm3);
    printer.print().to_string()
}

pub fn print_evaled_str(left: &str, right: &str) {
    let result = evaled_str(left);
    assert_eq!(result, right);
}

/// leftを評価したらちゃんとrightになるかどうかのテスト
pub fn print_syntax_sugar(left: &str, right: &str) {
    let result_left = evaled_str(left);
    let result_right = evaled_str(right);
    assert_eq!(result_left, result_right);
}

pub fn only_evaluate(s: &str) {
    let mut iter = s.bytes();
    let scanners: &Vec<&Scanner> = &all_scanners!();
    let lexer = Lexer::new(&mut iter, scanners);

    let vm = Rc::new(RefCell::new(Heliqs::new()));
    let vm2 = vm.clone();

    let mut parser = Parser::new(lexer, vm);
    parser.parse();

    let walker = Walker::new(vm2);
    walker.walk();
}

fn craete_vm<'a>() -> Rc<RefCell<Heliqs>> {
    Rc::new(RefCell::new(Heliqs::new()))
}
<|endoftext|>


<commit_before>// src/dao/account_dao.rs

/// Account DAO
/// Handle all database interaction for Accounts

// Import
extern crate mongodb;

// Import Modules
// Common Utilities
use ::bson::{Bson, Document};
use ::bson::oid::ObjectId;
use chrono::{UTC, Local, DateTime, TimeZone};
use ::mongodb::coll::options::FindOptions;
use ::mongodb::db::ThreadedDatabase;
use ::common::mm_result::{MMResult, MMError, MMErrorKind};
// Models
use ::models::account_model::{AccountModel, OutAccountModel};

// Constants
static MONEY_MAP_COLLECTION: &'static str = "money_maps";

/// Account DAO
pub struct AccountDAO{
    db: mongodb::db::Database
}

// Account DAO Methods
impl AccountDAO{
    /// Create AccountDAO
    ///
    /// # Arguments
    /// db - mongodb::db::Database Cloned database connection
    ///
    /// # Returns
    /// `AccountDAO`
    pub fn new(db: mongodb::db::Database) -> AccountDAO{
        AccountDAO{
            db: db
        }
    }

    /// Find All Money Map accounts for filter
    ///
    /// # Arguments
    /// self
    /// filter - Option<Document> The find filter
    ///
    /// # Returns
    /// `Option<Vec<OutAccountModel>>`
    pub fn find(self, filter: Option<Document>) -> Option<Vec<OutAccountModel>>{
        let coll = self.db.collection(MONEY_MAP_COLLECTION);
        let mut accounts = Vec::new();

        let mut find_options = FindOptions::new();
        find_options.projection = Some(doc!{
            "_id" => 0,
            "name" => 0,
            "users" => 0,
            "deleted" => 0
        });

        match coll.find_one(filter, Some(find_options)){
            Ok(result) => {
                match result{
                    Some(document) => {
                        if let Some(raw_accounts) = document.get("accounts"){
                            if let &Bson::Array(ref raw_accounts_arr) = raw_accounts{
                                for acc in raw_accounts_arr {
                                    if let &Bson::Document(ref acc_doc) = acc{
                                        accounts.push(document_to_model(acc_doc));
                                    }
                                }
                            }
                        }
                    },
                    None => {
                        //Could not find money map for user
                        return None
                    }
                }
            },
            Err(e) => {
                error!("Find All accounts failed: {}", e);
                return None;
            }
        }
        Some(accounts)
    }// end find

    /// Create Account
    /// Save account in specified money map
    ///
    /// # Arguments
    /// self
    /// mm_id - &str - Money Map ID
    /// account - &AccountModel The account
    ///
    /// # Returns
    /// `MMResult<AccountModel>`
    pub fn create(self, mm_id: ObjectId, account: &AccountModel) -> MMResult<AccountModel>{
        let coll = self.db.collection(MONEY_MAP_COLLECTION);

        let filter = doc! {
            "_id" => ( mm_id )
        };

        // Build `$push` document to update money map and add account
        let id = ObjectId::new().unwrap();
        let timestamp = Local::now().timestamp();
        let update_doc = doc! {
            "$push" => {
                "accounts" => {
                    "_id" => (Bson::ObjectId(id.clone())),
                    "name" => (match account.get_name(){Some(val) => val, None => "".to_string()}),
                    "account_type" => (match account.get_account_type(){Some(val) => val, None => "".to_string()}),
                    "created" => (Bson::TimeStamp(timestamp.clone()))
                }
            }
        };

        // Update the money map and add account
        match coll.update_one(filter.clone(), update_doc.clone(), None){
            Ok(result) => {
                if result.acknowledged && result.modified_count > 0 {
                    let mut new_account = account.clone();
                    new_account.set_id(Some(id));
                    new_account.set_created(Some(timestamp));
                    Ok(new_account)
                }else{
                    Err(MMError::new("Unable to add account to money map.", MMErrorKind::DAO))
                }
            },
            Err(e) => {
                error!("{}", e);
                Err(MMError::new("Failed to add account to money map.", MMErrorKind::DAO))
            }
        }
    }// end create

    /// Update an existing acount
    ///
    /// # Arguments
    /// self
    /// mm_id ObjectId The Money Map ID
    /// user_id ObjectId The Money Map ID
    /// &account - AccountModel
    ///
    /// # Returns
    /// `MMResult<AccountModel>` The updated money map if successful, None otherwise
    pub fn update(&self, mm_id: ObjectId, user_id: ObjectId, account: &AccountModel) -> MMResult<AccountModel>{
        let coll = self.db.collection(MONEY_MAP_COLLECTION);

        let filter = doc! {
            //Money Map Information
            "_id" => mm_id,
            "users" => {
                "$elemMatch" => {
                    "user_id" => user_id
                }
            },
            "deleted" => {
                "$ne" => true
            },
            //Account Information
            "accounts._id" => ( account.get_id().unwrap() )
        };

        // Build `$set` document to update document
        let mut set_doc = doc!{};
        if let Some(name) = account.get_name(){
            set_doc.insert_bson("accounts.$.name".to_string(), Bson::String(name));
        }
        let update_doc = doc! {"$set" => set_doc};

        // Update the money map
        match coll.update_one(filter.clone(), update_doc.clone(), None){
            Ok(result) => {
                if result.matched_count <= 0 {
                    Err(MMError::new("Unable to find account", MMErrorKind::DAO))
                }else if result.modified_count == 1 {
                    //Ok(self.find_one(Some(filter), None).unwrap())
                    // TODO Fetch and return updated account
                    Ok(AccountModel{
                        id:None,
                        name:None,
                        account_type:None,
                        created:None
                    })
                }else{
                    Err(MMError::new("Unable to save account", MMErrorKind::DAO))
                }
            },
            Err(e) => {
                error!("{}", e);
                Err(MMError::new("Failed to update money map.", MMErrorKind::DAO))
            }
        }
    }// end update
}

/// Create OutAccountModel from Document
///
/// # Arguments
/// self
/// doc - Document
///
/// # Returns
/// `OutAccountModel`
fn document_to_model(doc: &Document) -> OutAccountModel{
    OutAccountModel{
        id: match doc.get("_id"){
            Some(obj_id) => match obj_id{ &Bson::ObjectId(ref id) => Some(id.clone()), _ => None},
            _ => None
        },
        name: match doc.get("name"){
            Some(&Bson::String(ref name)) => Some(name.clone()),
            _ => None
        },
        account_type: match doc.get("account_type"){
            Some(&Bson::String(ref account_type)) => Some(account_type.clone()),
            _ => None
        },
        created: match doc.get("created"){
            Some(&Bson::TimeStamp(ref timestamp)) => {
                Some(Local.timestamp(timestamp.clone(), 0).to_rfc2822())
            },
            _ => None
        }
    }
}
<commit_msg>Save account type on edit account<commit_after>// src/dao/account_dao.rs

/// Account DAO
/// Handle all database interaction for Accounts

// Import
extern crate mongodb;

// Import Modules
// Common Utilities
use ::bson::{Bson, Document};
use ::bson::oid::ObjectId;
use chrono::{UTC, Local, DateTime, TimeZone};
use ::mongodb::coll::options::FindOptions;
use ::mongodb::db::ThreadedDatabase;
use ::common::mm_result::{MMResult, MMError, MMErrorKind};
// Models
use ::models::account_model::{AccountModel, OutAccountModel};

// Constants
static MONEY_MAP_COLLECTION: &'static str = "money_maps";

/// Account DAO
pub struct AccountDAO{
    db: mongodb::db::Database
}

// Account DAO Methods
impl AccountDAO{
    /// Create AccountDAO
    ///
    /// # Arguments
    /// db - mongodb::db::Database Cloned database connection
    ///
    /// # Returns
    /// `AccountDAO`
    pub fn new(db: mongodb::db::Database) -> AccountDAO{
        AccountDAO{
            db: db
        }
    }

    /// Find All Money Map accounts for filter
    ///
    /// # Arguments
    /// self
    /// filter - Option<Document> The find filter
    ///
    /// # Returns
    /// `Option<Vec<OutAccountModel>>`
    pub fn find(self, filter: Option<Document>) -> Option<Vec<OutAccountModel>>{
        let coll = self.db.collection(MONEY_MAP_COLLECTION);
        let mut accounts = Vec::new();

        let mut find_options = FindOptions::new();
        find_options.projection = Some(doc!{
            "_id" => 0,
            "name" => 0,
            "users" => 0,
            "deleted" => 0
        });

        match coll.find_one(filter, Some(find_options)){
            Ok(result) => {
                match result{
                    Some(document) => {
                        if let Some(raw_accounts) = document.get("accounts"){
                            if let &Bson::Array(ref raw_accounts_arr) = raw_accounts{
                                for acc in raw_accounts_arr {
                                    if let &Bson::Document(ref acc_doc) = acc{
                                        accounts.push(document_to_model(acc_doc));
                                    }
                                }
                            }
                        }
                    },
                    None => {
                        //Could not find money map for user
                        return None
                    }
                }
            },
            Err(e) => {
                error!("Find All accounts failed: {}", e);
                return None;
            }
        }
        Some(accounts)
    }// end find

    /// Create Account
    /// Save account in specified money map
    ///
    /// # Arguments
    /// self
    /// mm_id - &str - Money Map ID
    /// account - &AccountModel The account
    ///
    /// # Returns
    /// `MMResult<AccountModel>`
    pub fn create(self, mm_id: ObjectId, account: &AccountModel) -> MMResult<AccountModel>{
        let coll = self.db.collection(MONEY_MAP_COLLECTION);

        let filter = doc! {
            "_id" => ( mm_id )
        };

        // Build `$push` document to update money map and add account
        let id = ObjectId::new().unwrap();
        let timestamp = Local::now().timestamp();
        let update_doc = doc! {
            "$push" => {
                "accounts" => {
                    "_id" => (Bson::ObjectId(id.clone())),
                    "name" => (match account.get_name(){Some(val) => val, None => "".to_string()}),
                    "account_type" => (match account.get_account_type(){Some(val) => val, None => "".to_string()}),
                    "created" => (Bson::TimeStamp(timestamp.clone()))
                }
            }
        };

        // Update the money map and add account
        match coll.update_one(filter.clone(), update_doc.clone(), None){
            Ok(result) => {
                if result.acknowledged && result.modified_count > 0 {
                    let mut new_account = account.clone();
                    new_account.set_id(Some(id));
                    new_account.set_created(Some(timestamp));
                    Ok(new_account)
                }else{
                    Err(MMError::new("Unable to add account to money map.", MMErrorKind::DAO))
                }
            },
            Err(e) => {
                error!("{}", e);
                Err(MMError::new("Failed to add account to money map.", MMErrorKind::DAO))
            }
        }
    }// end create

    /// Update an existing acount
    ///
    /// # Arguments
    /// self
    /// mm_id ObjectId The Money Map ID
    /// user_id ObjectId The Money Map ID
    /// &account - AccountModel
    ///
    /// # Returns
    /// `MMResult<AccountModel>` The updated money map if successful, None otherwise
    pub fn update(&self, mm_id: ObjectId, user_id: ObjectId, account: &AccountModel) -> MMResult<AccountModel>{
        let coll = self.db.collection(MONEY_MAP_COLLECTION);

        let filter = doc! {
            //Money Map Information
            "_id" => mm_id,
            "users" => {
                "$elemMatch" => {
                    "user_id" => user_id
                }
            },
            "deleted" => {
                "$ne" => true
            },
            //Account Information
            "accounts._id" => ( account.get_id().unwrap() )
        };

        // Build `$set` document to update document
        let mut set_doc = doc!{};
        if let Some(name) = account.get_name(){
            set_doc.insert_bson("accounts.$.name".to_string(), Bson::String(name));
        }
        if let Some(account_type) = account.get_account_type(){
            set_doc.insert_bson("accounts.$.account_type".to_string(), Bson::String(account_type));
        }
        let update_doc = doc! {"$set" => set_doc};

        // Update the money map
        match coll.update_one(filter.clone(), update_doc.clone(), None){
            Ok(result) => {
                if result.matched_count <= 0 {
                    Err(MMError::new("Unable to find account", MMErrorKind::DAO))
                }else if result.modified_count == 1 {
                    //Ok(self.find_one(Some(filter), None).unwrap())
                    // TODO Fetch and return updated account
                    Ok(AccountModel{
                        id:None,
                        name:None,
                        account_type:None,
                        created:None
                    })
                }else{
                    Err(MMError::new("Unable to save account", MMErrorKind::DAO))
                }
            },
            Err(e) => {
                error!("{}", e);
                Err(MMError::new("Failed to update money map.", MMErrorKind::DAO))
            }
        }
    }// end update
}

/// Create OutAccountModel from Document
///
/// # Arguments
/// self
/// doc - Document
///
/// # Returns
/// `OutAccountModel`
fn document_to_model(doc: &Document) -> OutAccountModel{
    OutAccountModel{
        id: match doc.get("_id"){
            Some(obj_id) => match obj_id{ &Bson::ObjectId(ref id) => Some(id.clone()), _ => None},
            _ => None
        },
        name: match doc.get("name"){
            Some(&Bson::String(ref name)) => Some(name.clone()),
            _ => None
        },
        account_type: match doc.get("account_type"){
            Some(&Bson::String(ref account_type)) => Some(account_type.clone()),
            _ => None
        },
        created: match doc.get("created"){
            Some(&Bson::TimeStamp(ref timestamp)) => {
                Some(Local.timestamp(timestamp.clone(), 0).to_rfc2822())
            },
            _ => None
        }
    }
}
<|endoftext|>