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

//! A container for all the tabs being edited. Also functions as main dispatch for RPC.

use std::collections::BTreeMap;
use std::sync::{Arc, Mutex};
use serde_json::Value;
use serde_json::builder::ObjectBuilder;

use xi_rope::rope::Rope;
use editor::Editor;
use rpc::{TabCommand, EditCommand};
use run_plugin::PluginPeer;
use MainPeer;

pub struct Tabs {
    tabs: BTreeMap<String, Arc<Mutex<Editor>>>,
    id_counter: usize,
    kill_ring: Mutex<Rope>,
}

pub struct TabCtx<'a> {
    tab: &'a str,
    kill_ring: &'a Mutex<Rope>,
    rpc_peer: &'a MainPeer,
    self_ref: Arc<Mutex<Editor>>,
}

pub struct PluginCtx {
    main_peer: MainPeer,
    plugin_peer: Option<PluginPeer>,
    editor: Arc<Mutex<Editor>>,
}

impl Tabs {
    pub fn new() -> Tabs {
        Tabs {
            tabs: BTreeMap::new(),
            id_counter: 0,
            kill_ring: Mutex::new(Rope::from("")),
        }
    }

    pub fn do_rpc(&mut self, cmd: TabCommand, rpc_peer: MainPeer) -> Option<Value> {
        use rpc::TabCommand::*;

        match cmd {
            NewTab => Some(Value::String(self.do_new_tab())),

            DeleteTab { tab_name } => {
                self.do_delete_tab(tab_name);
                None
            },

            Edit { tab_name, edit_command } => self.do_edit(tab_name, edit_command, &rpc_peer),
        }
    }

    fn do_new_tab(&mut self) -> String {
        self.new_tab()
    }

    fn do_delete_tab(&mut self, tab: &str) {
        self.delete_tab(tab);
    }

    fn do_edit(&mut self, tab: &str, cmd: EditCommand, rpc_peer: &MainPeer)
            -> Option<Value> {
        if let Some(editor) = self.tabs.get(tab) {
            let tab_ctx = TabCtx {
                tab: tab,
                kill_ring: &self.kill_ring,
                rpc_peer: rpc_peer,
                self_ref: editor.clone(),
            };
            editor.lock().unwrap().do_rpc(cmd, tab_ctx)
        } else {
            print_err!("tab not found: {}", tab);
            None
        }
    }

    fn new_tab(&mut self) -> String {
        let tabname = self.id_counter.to_string();
        self.id_counter += 1;
        let editor = Editor::new();
        self.tabs.insert(tabname.clone(), Arc::new(Mutex::new(editor)));
        tabname
    }

    fn delete_tab(&mut self, tabname: &str) {
        self.tabs.remove(tabname);
    }
}

impl<'a> TabCtx<'a> {
    pub fn update_tab(&self, update: &Value) {
        self.rpc_peer.send_rpc_notification("update",
            &ObjectBuilder::new()
                .insert("tab", self.tab)
                .insert("update", update)
                .unwrap());
    }

    pub fn get_kill_ring(&self) -> Rope {
        self.kill_ring.lock().unwrap().clone()
    }

    pub fn set_kill_ring(&self, val: Rope) {
        let mut kill_ring = self.kill_ring.lock().unwrap();
        *kill_ring = val;
    }

    pub fn get_self_ref(&self) -> Arc<Mutex<Editor>> {
        self.self_ref.clone()
    }

    pub fn to_plugin_ctx(&self) -> PluginCtx {
        PluginCtx {
            main_peer: self.rpc_peer.clone(),
            plugin_peer: None,
            editor: self.get_self_ref(),
        }
    }
}

impl PluginCtx {
    pub fn on_plugin_connect(&mut self, peer: PluginPeer) {
        let buf_size = self.editor.lock().unwrap().plugin_buf_size();
        peer.send_rpc_notification("ping_from_editor", &Value::Array(vec![Value::U64(buf_size as u64)]));
        self.plugin_peer = Some(peer);
    }

    // Note: the following are placeholders for prototyping, and are not intended to
    // deal with asynchrony or be efficient.

    pub fn n_lines(&self) -> usize {
        self.editor.lock().unwrap().plugin_n_lines()
    }

    pub fn get_line(&self, line_num: usize) -> String {
        self.editor.lock().unwrap().plugin_get_line(line_num)
    }

    pub fn set_line_fg_spans(&self, line_num: usize, spans: &Value) {
        self.editor.lock().unwrap().plugin_set_line_fg_spans(line_num, spans);
    }

    pub fn alert(&self, msg: &str) {
        self.main_peer.send_rpc_notification("alert",
            &ObjectBuilder::new()
                .insert("msg", msg)
                .unwrap());
    }
}
<commit_msg>update PluginCtx to contain a TabCtx<commit_after>// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A container for all the tabs being edited. Also functions as main dispatch for RPC.

use std::collections::BTreeMap;
use std::sync::{Arc, Mutex};
use serde_json::Value;
use serde_json::builder::ObjectBuilder;

use xi_rope::rope::Rope;
use editor::Editor;
use rpc::{TabCommand, EditCommand};
use run_plugin::PluginPeer;
use MainPeer;

pub struct Tabs {
    tabs: BTreeMap<String, Arc<Mutex<Editor>>>,
    id_counter: usize,
    kill_ring: Arc<Mutex<Rope>>,
}

#[derive(Clone)]
pub struct TabCtx {
    tab: String,
    kill_ring: Arc<Mutex<Rope>>,
    rpc_peer: MainPeer,
    self_ref: Arc<Mutex<Editor>>,
}

pub struct PluginCtx {
    tab_ctx: TabCtx,
    rpc_peer: Option<PluginPeer>,
}

impl Tabs {
    pub fn new() -> Tabs {
        Tabs {
            tabs: BTreeMap::new(),
            id_counter: 0,
            kill_ring: Arc::new(Mutex::new(Rope::from(""))),
        }
    }

    pub fn do_rpc(&mut self, cmd: TabCommand, rpc_peer: MainPeer) -> Option<Value> {
        use rpc::TabCommand::*;

        match cmd {
            NewTab => Some(Value::String(self.do_new_tab())),

            DeleteTab { tab_name } => {
                self.do_delete_tab(tab_name);
                None
            },

            Edit { tab_name, edit_command } => self.do_edit(tab_name, edit_command, rpc_peer),
        }
    }

    fn do_new_tab(&mut self) -> String {
        self.new_tab()
    }

    fn do_delete_tab(&mut self, tab: &str) {
        self.delete_tab(tab);
    }

    fn do_edit(&mut self, tab: &str, cmd: EditCommand, rpc_peer: MainPeer)
            -> Option<Value> {
        if let Some(editor) = self.tabs.get(tab) {
            let tab_ctx = TabCtx {
                tab: tab.to_string(),
                kill_ring: self.kill_ring.clone(),
                rpc_peer: rpc_peer,
                self_ref: editor.clone(),
            };
            editor.lock().unwrap().do_rpc(cmd, tab_ctx)
        } else {
            print_err!("tab not found: {}", tab);
            None
        }
    }

    fn new_tab(&mut self) -> String {
        let tabname = self.id_counter.to_string();
        self.id_counter += 1;
        let editor = Editor::new();
        self.tabs.insert(tabname.clone(), Arc::new(Mutex::new(editor)));
        tabname
    }

    fn delete_tab(&mut self, tabname: &str) {
        self.tabs.remove(tabname);
    }
}

impl TabCtx {
    pub fn update_tab(&self, update: &Value) {
        self.rpc_peer.send_rpc_notification("update",
            &ObjectBuilder::new()
                .insert("tab", &self.tab)
                .insert("update", update)
                .unwrap());
    }

    pub fn get_kill_ring(&self) -> Rope {
        self.kill_ring.lock().unwrap().clone()
    }

    pub fn set_kill_ring(&self, val: Rope) {
        let mut kill_ring = self.kill_ring.lock().unwrap();
        *kill_ring = val;
    }

    pub fn to_plugin_ctx(&self) -> PluginCtx {
        PluginCtx {
            tab_ctx: self.clone(),
            rpc_peer: None,
        }
    }
}

impl PluginCtx {
    pub fn on_plugin_connect(&mut self, peer: PluginPeer) {
        let buf_size = self.tab_ctx.self_ref.lock().unwrap().plugin_buf_size();
        peer.send_rpc_notification("ping_from_editor", &Value::Array(vec![Value::U64(buf_size as u64)]));
        self.rpc_peer = Some(peer);
    }

    // Note: the following are placeholders for prototyping, and are not intended to
    // deal with asynchrony or be efficient.

    pub fn n_lines(&self) -> usize {
        self.tab_ctx.self_ref.lock().unwrap().plugin_n_lines()
    }

    pub fn get_line(&self, line_num: usize) -> String {
        self.tab_ctx.self_ref.lock().unwrap().plugin_get_line(line_num)
    }

    pub fn set_line_fg_spans(&self, line_num: usize, spans: &Value) {
        self.tab_ctx.self_ref.lock().unwrap().plugin_set_line_fg_spans(line_num, spans);
    }

    pub fn alert(&self, msg: &str) {
        self.tab_ctx.rpc_peer.send_rpc_notification("alert",
            &ObjectBuilder::new()
                .insert("msg", msg)
                .unwrap());
    }
}
<|endoftext|>


<commit_before><commit_msg>Converted PortReader and ChanWriter to use Vec.<commit_after><|endoftext|>


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

use LinkerFlavor;
use super::{LinkArgs, Target, TargetOptions};
use super::emscripten_base::{cmd};

pub fn target() -> Result<Target, String> {
    let mut post_link_args = LinkArgs::new();
    post_link_args.insert(LinkerFlavor::Em,
                          vec!["-s".to_string(),
                               "WASM=1".to_string(),
                               "-s".to_string(),
                               "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);

    let opts = TargetOptions {
        linker: cmd("emcc"),
        ar: cmd("emar"),

        dynamic_linking: false,
        executables: true,
        // Today emcc emits two files - a .js file to bootstrap and
        // possibly interpret the wasm, and a .wasm file
        exe_suffix: ".js".to_string(),
        linker_is_gnu: true,
        link_env: vec![("EMCC_WASM_BACKEND".to_string(), "1".to_string())],
        allow_asm: false,
        obj_is_bitcode: true,
        is_like_emscripten: true,
        max_atomic_width: Some(32),
        post_link_args: post_link_args,
        target_family: Some("unix".to_string()),
        .. Default::default()
    };
    Ok(Target {
        llvm_target: "wasm32-unknown-unknown".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_os: "emscripten".to_string(),
        target_env: "".to_string(),
        target_vendor: "unknown".to_string(),
        data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
        arch: "wasm32".to_string(),
        linker_flavor: LinkerFlavor::Em,
        options: opts,
    })
}
<commit_msg>Auto merge of #43344 - tlively:wasm-debug, r=alexcrichton<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use LinkerFlavor;
use super::{LinkArgs, Target, TargetOptions};
use super::emscripten_base::{cmd};

pub fn target() -> Result<Target, String> {
    let mut post_link_args = LinkArgs::new();
    post_link_args.insert(LinkerFlavor::Em,
                          vec!["-s".to_string(),
                               "WASM=1".to_string(),
                               "-s".to_string(),
                               "ASSERTIONS=1".to_string(),
                               "-s".to_string(),
                               "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(),
                               "-g3".to_string()]);

    let opts = TargetOptions {
        linker: cmd("emcc"),
        ar: cmd("emar"),

        dynamic_linking: false,
        executables: true,
        // Today emcc emits two files - a .js file to bootstrap and
        // possibly interpret the wasm, and a .wasm file
        exe_suffix: ".js".to_string(),
        linker_is_gnu: true,
        link_env: vec![("EMCC_WASM_BACKEND".to_string(), "1".to_string())],
        allow_asm: false,
        obj_is_bitcode: true,
        is_like_emscripten: true,
        max_atomic_width: Some(32),
        post_link_args: post_link_args,
        target_family: Some("unix".to_string()),
        .. Default::default()
    };
    Ok(Target {
        llvm_target: "wasm32-unknown-unknown".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_os: "emscripten".to_string(),
        target_env: "".to_string(),
        target_vendor: "unknown".to_string(),
        data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
        arch: "wasm32".to_string(),
        linker_flavor: LinkerFlavor::Em,
        options: opts,
    })
}
<|endoftext|>


<commit_before><commit_msg>Add new file to mcts lib that was previously overlooked.<commit_after>use super::Statistics;
use std::sync::atomic;

// pub type Graph<G: Game> =
//     search_graph::Graph<G::State, VertexData, EdgeData<G::Statistics, G::Action>>;
// pub type Vertex<'a, G: 'a + Game> =
//     search_graph::nav::Node<'a, G::State, VertexData, EdgeData<G::Statistics, G::Action>>;
// pub type Edge<'a, G: 'a + Game> =
//     search_graph::nav::Edge<'a, G::State, VertexData, EdgeData<G::Statistics, G::Action>>;
// pub type ChildList<'a, G: 'a + Game> =
//     search_graph::nav::ChildList<'a, G::State, VertexData, EdgeData<G::Statistics, G::Action>>;
// pub type ChildListIter<'a, G: 'a + Game> =
//     search_graph::nav::ChildListIter<'a, G::State, VertexData, EdgeData<G::Statistics, G::Action>>;
// pub type ParentList<'a, G: 'a + Game> =
//     search_graph::nav::ParentList<'a, G::State, VertexData, EdgeData<G::Statistics, G::Action>>;
// pub type ParentListIter<'a, G: 'a + Game> =
//     search_graph::nav::ParentListIter<'a, G::State, VertexData, EdgeData<G::Statistics, G::Action>>;
// pub type MutVertex<'a, G: 'a + Game> =
//     search_graph::mutators::MutNode<'a, G::State, VertexData, EdgeData<G::Statistics, G::Action>>;

#[derive(Debug)]
pub struct VertexData {
    expanded: atomic::AtomicBool,
}

impl VertexData {
    pub fn expanded(&self) -> bool {
        self.expanded.load(atomic::Ordering::Acquire)
    }

    pub fn mark_expanded(&self) -> bool {
        // TODO: do we really need Ordering::SeqCst?
        self.expanded.swap(true, atomic::Ordering::AcqRel)
    }
}

impl Clone for VertexData {
    fn clone(&self) -> Self {
        VertexData {
            // TODO: do we really need Ordering::SeqCst?
            expanded: atomic::AtomicBool::new(
                self.expanded.load(atomic::Ordering::Acquire)),
        }
    }
}

impl Default for VertexData {
    fn default() -> Self {
        VertexData {
            expanded: atomic::AtomicBool::new(false),
        }
    }
}

#[derive(Debug)]
pub struct EdgeData<S, A> where S: Statistics {
    rollout_epoch: atomic::AtomicUsize,
    backtrace_epoch: atomic::AtomicUsize,
    visited: atomic::AtomicBool,
    pub action: A,
    pub statistics: S,
}

impl<S, A> Clone for EdgeData<S, A> where S: Statistics + Clone, A: Clone {
    fn clone(&self) -> Self {
        EdgeData {
            // TODO: do we really need Ordering::SeqCst?
            rollout_epoch: atomic::AtomicUsize::new(
                self.rollout_epoch.load(atomic::Ordering::Acquire)),
            backtrace_epoch: atomic::AtomicUsize::new(
                self.backtrace_epoch.load(atomic::Ordering::Acquire)),
            visited: atomic::AtomicBool::new(
                self.visited.load(atomic::Ordering::Acquire)),
            action: self.action.clone(),
            statistics: self.statistics.clone(),
        }
    }
}

impl<S, A> EdgeData<S, A> where S: Statistics {
    pub fn new(action: A) -> Self {
        EdgeData {
            rollout_epoch: atomic::AtomicUsize::new(0),
            backtrace_epoch: atomic::AtomicUsize::new(0),
            visited: atomic::AtomicBool::new(false),
            action: action,
            statistics: Default::default(),
        }
    }

    // Returns true iff edge was not previously marked as visited.
    pub fn mark_visited_in_rollout_epoch(&self, epoch: usize) -> bool {
        // TODO: do we really need Ordering::SeqCst?
        let previous_value = self.rollout_epoch.swap(epoch, atomic::Ordering::AcqRel);
        assert!(previous_value <= epoch,
                "Previous rollout epoch > current epoch ({} > {})", previous_value, epoch);
        previous_value >= epoch
    }

    // Returns true iff edge was not previously marked as visited.
    pub fn visited_in_backtrace_epoch(&self, epoch: usize) -> bool {
        // TODO: do we really need Ordering::SeqCst?
        let previous_value = self.backtrace_epoch.swap(epoch, atomic::Ordering::AcqRel);
        assert!(previous_value <= epoch,
                "Previous backtrace epoch > current epoch ({} > {})", previous_value, epoch);
        previous_value >= epoch
    }

    // Returns true iff previously visited.
    pub fn mark_visited(&self) -> bool {
        // TODO: do we really need Ordering::SeqCst?
        self.visited.swap(true, atomic::Ordering::AcqRel)
    }
}
<|endoftext|>


<commit_before>#![feature(rustc_attrs)]

struct Foo {
    x: u8
}

impl Foo {
    // Changing the item `new`...
    #[rustc_if_this_changed(HirBody)]
    fn new() -> Foo {
        Foo { x: 0 }
    }

    // ...should not cause us to recompute the tables for `with`!
    #[rustc_then_this_would_need(Tables)] //~ ERROR no path
    fn with(x: u8) -> Foo {
        Foo { x: x }
    }
}

fn main() {
    let f = Foo::new();
    let g = Foo::with(22);
    assert_eq!(f.x, g.x - 22);
}
<commit_msg>pacify the mercilous tidy<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(rustc_attrs)]

struct Foo {
    x: u8
}

impl Foo {
    // Changing the item `new`...
    #[rustc_if_this_changed(HirBody)]
    fn new() -> Foo {
        Foo { x: 0 }
    }

    // ...should not cause us to recompute the tables for `with`!
    #[rustc_then_this_would_need(Tables)] //~ ERROR no path
    fn with(x: u8) -> Foo {
        Foo { x: x }
    }
}

fn main() {
    let f = Foo::new();
    let g = Foo::with(22);
    assert_eq!(f.x, g.x - 22);
}
<|endoftext|>


<commit_before><commit_msg>:sparkles: add postman<commit_after>// CITA
// Copyright 2016-2018 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use cita_types::{Address, H256};
use core::contracts::solc::sys_config::ChainId;
use core::libexecutor::block::{ClosedBlock, OpenBlock};
use core::libexecutor::call_request::CallRequest;
use crossbeam_channel::{Receiver, Sender};
use error::ErrorCode;
use jsonrpc_types::rpctypes::{BlockNumber, CountOrCode};
use libproto::auth::Miscellaneous;
use libproto::blockchain::{RichStatus, StateSignal};
use libproto::request::Request_oneof_req as Request;
use libproto::router::{MsgType, RoutingKey, SubModules};
use libproto::{request, response, ConsensusConfig, ExecutedResult, Message};
use proof::BftProof;
use serde_json;
use std::convert::{Into, TryFrom, TryInto};
use std::u8;
use types::ids::BlockId;

use core::libexecutor::command;

use super::backlogs::Backlogs;

pub struct Postman {
    backlogs: Backlogs,
    mq_req_receiver: Receiver<(String, Vec<u8>)>,
    mq_resp_sender: Sender<(String, Vec<u8>)>,
    fsm_req_sender: Sender<OpenBlock>,
    fsm_resp_receiver: Receiver<(ClosedBlock, ExecutedResult)>,
    command_req_sender: Sender<command::Command>,
    command_resp_receiver: Receiver<command::CommandResp>,
}

impl Postman {
    pub fn new(
        current_height: u64,
        mq_req_receiver: Receiver<(String, Vec<u8>)>,
        mq_resp_sender: Sender<(String, Vec<u8>)>,
        fsm_req_sender: Sender<OpenBlock>,
        fsm_resp_receiver: Receiver<(ClosedBlock, ExecutedResult)>,
        command_req_sender: Sender<command::Command>,
        command_resp_receiver: Receiver<command::CommandResp>,
    ) -> Self {
        Postman {
            backlogs: Backlogs::new(current_height),
            mq_req_receiver,
            mq_resp_sender,
            fsm_req_sender,
            fsm_resp_receiver,
            command_req_sender,
            command_resp_receiver,
        }
    }

    pub fn do_loop(&mut self) {
        loop {
            match self.recv() {
                (None, None) | (Some(_), Some(_)) => return,
                (Some((key, msg_vec)), None) => {
                    match self.handle_mq_message(key.as_str(), msg_vec) {
                        Err(rollback_id) => {
                            self.close(rollback_id);
                            return;
                        }
                        Ok(_) => {}
                    }
                }
                (None, Some((closed_block, executed_result))) => {
                    self.handle_fsm_response(closed_block, executed_result);
                    self.execute_next_block();
                }
            }
        }
    }

    // call this function every times Executor start/restart, to broadcast current state
    // to cita-chain. This broadcast state only contains system config but not block data,
    // cita-chain would deal with it.
    pub fn bootstrap_broadcast(&self, consensus_config: ConsensusConfig) {
        let mut executed_result = ExecutedResult::new();
        executed_result.set_config(consensus_config);
        let msg: Message = executed_result.into();
        self.response_mq(
            routing_key!(Executor >> ExecutedResult).into(),
            msg.try_into().unwrap(),
        );
    }

    // make sure executor exit also
    fn close(&self, rollback_id: BlockId) {
        command::exit(
            &self.command_req_sender,
            &self.command_resp_receiver,
            rollback_id,
        );
    }

    #[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
    fn recv(
        &self,
    ) -> (
        Option<(String, Vec<u8>)>,
        Option<(ClosedBlock, ExecutedResult)>,
    ) {
        select! {
            recv(self.mq_req_receiver, mq_req) => {
                match mq_req {
                    Some(mq_req) => (Some(mq_req), None),
                    None => (None, None),
                }
            },
            recv(self.fsm_resp_receiver, fsm_resp) => {
                match fsm_resp {
                    Some(fsm_resp) => (None, Some(fsm_resp)),
                    None => (None, None),
                }
            }
        }
    }

    // update executed result into backlogs based on arrived result from executor, and process
    // the next height if possible
    fn handle_fsm_response(&mut self, closed_block: ClosedBlock, executed_result: ExecutedResult) {
        let height = closed_block.number();
        info!("postman receive {}-th ClosedBlock from executor", height);
        self.backlogs
            .insert_result(height, closed_block, executed_result);
        self.maybe_grow_up();
    }

    fn handle_mq_message(&mut self, key: &str, msg_vec: Vec<u8>) -> Result<(), BlockId> {
        let mut msg = Message::try_from(msg_vec).unwrap();
        trace!("receive {} from RabbitMQ", key);
        match RoutingKey::from(key) {
            routing_key!(Auth >> MiscellaneousReq) => {
                self.reply_auth_miscellaneous();
            }

            routing_key!(Chain >> Request) => {
                let req = msg.take_request().unwrap();
                self.reply_chain_request(req);
            }

            routing_key!(Chain >> RichStatus) => {
                if let Some(status) = msg.take_rich_status() {
                    self.update_by_rich_status(&status);
                };
            }

            routing_key!(Chain >> StateSignal) => {
                if let Some(state_signal) = msg.take_state_signal() {
                    self.reply_chain_state_signal(&state_signal)?;
                }
            }

            routing_key!(Consensus >> SignedProposal)
            | routing_key!(Net >> SignedProposal)
            | routing_key!(Consensus >> BlockWithProof)
            | routing_key!(Net >> SyncResponse)
            | routing_key!(Chain >> LocalSync) => {
                self.update_backlog(key, msg);
                self.maybe_grow_up();
                self.execute_next_block();
            }

            _ => {
                error!("receive unknown key: {} !!!!", key);
            }
        }
        Ok(())
    }

    // cita-chain broadcast StateSignal to indicate its state. So we could figure out
    // which blocks cita-chain lack of, then re-send the lacking blocks to cita-chain.
    fn reply_chain_state_signal(&self, state_signal: &StateSignal) -> Result<(), BlockId> {
        let specified_height = state_signal.get_height();
        if specified_height < self.get_current_height() {
            self.send_executed_info_to_chain(specified_height + 1)?;
            for height in self.backlogs.completed_keys() {
                if *height > specified_height + 1 {
                    self.send_executed_info_to_chain(*height)?;
                }
            }
        } else if specified_height > self.get_current_height() {
            self.signal_to_chain();
        }
        Ok(())
    }

    fn send_executed_info_to_chain(&self, height: u64) -> Result<(), BlockId> {
        if height > self.get_current_height() {
            error!("This must be because the Executor database was manually deleted.");
            return Ok(());
        }

        let executed_result = self.backlogs.get_completed_result(height);

        // Consider an abnormal case:
        //
        // 1. Our local node is height 50, and lags behind others
        //    100 blocks, so let's start to synchronize!
        //
        // 2. During synchronizing, cita-executor catches up to height 60, and sends
        //    notifications `ExecutedResult<height=51..60>` (from executing sync blocks) to
        //    cita-chain.
        //
        // 3. But suddenly cita-executor and cita-chain crashes before cita-chain
        //    receiving those `ExecutedResult<height=51..60>`, and even these within
        //    RabbitMQ be lost!
        //
        // 4. Cita-executor restart, its height is 60.
        //
        // 5. Cita-chain restart, its height is still 50.
        //
        // At this case above, cita-executor would hear `StateSignal<height=50>` from
        // cita-chain. But cita-executor could not anymore construct
        // `ExecutedResult<height=51..60>` based on its persisted data. It has to rollback
        // to 50 to keep equal to cita-chain, and then re-synchronize.
        //
        // Here the returned value `BlockId::Number(height - 1)` would be passed out to main()
        // thread. Then main() would restart executor thread and let executor starts with
        // `BlockId::Number(height - 1)`.
        if executed_result.is_none() {
            warn!("cita-chain(height={}) is lagging behind cita-executor(height={}), gonna roll back to {}", height, self.get_current_height(), height - 1);
            return Err(BlockId::Number(height - 1));
        }

        trace!("send {}-th ExecutedResult", height);
        let executed_result = executed_result.unwrap();
        let msg: Message = executed_result.into();
        self.response_mq(
            routing_key!(Executor >> ExecutedResult).into(),
            msg.try_into().unwrap(),
        );
        Ok(())
    }

    // TODO: check is_dup_block, hash, height
    fn update_backlog(&mut self, key: &str, mut msg: Message) {
        match RoutingKey::from(key) {
            // Proposal{proof: None, block: {body: Some, proof: None}}
            routing_key!(Consensus >> SignedProposal) | routing_key!(Net >> SignedProposal) => {
                let mut proposal = msg.take_signed_proposal().unwrap();
                let open_block = OpenBlock::from(proposal.take_proposal().take_block());
                let block_height = wrap_height(open_block.number() as usize);

                trace!("insert {}-th Proposal into backlog", block_height);
                self.backlogs.insert_open_block(block_height, open_block);
            }

            // BlockWithProof{proof: Some, block: {body: Some, proof: None}}
            routing_key!(Consensus >> BlockWithProof) => {
                let mut proofed = msg.take_block_with_proof().unwrap();
                let open_block = OpenBlock::from(proofed.take_blk());
                let proof = BftProof::from(proofed.take_proof());
                let proof_height = wrap_height(proof.height);
                let block_height = wrap_height(open_block.number() as usize);

                trace!("insert {}-th Proofed into backlog", block_height);
                self.backlogs.insert_open_block(block_height, open_block);
                self.backlogs.insert_proof(proof_height, proof);
            }

            // SyncBlock{proof: None, block: {body: Some, proof: Some}}
            routing_key!(Net >> SyncResponse) | routing_key!(Chain >> LocalSync) => {
                let mut sync_res = msg.take_sync_response().unwrap();
                for proto_block in sync_res.take_blocks().into_iter() {
                    let open_block = OpenBlock::from(proto_block);
                    let proof = BftProof::from(open_block.proof().clone());
                    let proof_height = wrap_height(proof.height);
                    let block_height = wrap_height(open_block.number() as usize);

                    trace!("insert {}-th Sync into backlog", block_height);
                    self.backlogs.insert_open_block(block_height, open_block);
                    self.backlogs.insert_proof(proof_height, proof);
                }
            }
            _ => unimplemented!(),
        }
    }

    /// Grow up if current block executed completely,
    /// 1. Update backlogs
    /// 2. Notify executor to grow up too
    /// 3. Delivery rich status of new height
    fn maybe_grow_up(&mut self) {
        let next_height = self.get_current_height() + 1;
        if self.backlogs.is_completed(next_height) {
            let backlog = self.backlogs.complete(next_height);
            let closed_block = backlog.clone_closed_block();

            // make sure executor grow up first
            trace!("postman notice executor to grow up to {}", next_height,);
            command::grow(
                &self.command_req_sender,
                &self.command_resp_receiver,
                closed_block,
            );

            self.send_executed_info_to_chain(next_height).unwrap();
            // FIXME self.pub_black_list(&closed_block, ctx_pub);
        }
    }

    fn execute_next_block(&mut self) {
        let next_height = self.get_current_height() + 1;
        if let Some(block) = self.backlogs.get_open_block(next_height) {
            if let Some(closed_block) = self.backlogs.get_closed_block(next_height) {
                if closed_block.is_equivalent(&block) {
                    return;
                }
            }
            trace!("postman send {}-th block to executor", block.number());
            self.fsm_req_sender.send(block);
        }
    }

    fn update_by_rich_status(&mut self, rich_status: &RichStatus) {
        let next_height = rich_status.get_height() + 1;
        self.backlogs.prune(next_height);
    }

    fn reply_auth_miscellaneous(&self) {
        let mut miscellaneous = Miscellaneous::new();
        let option = command::chain_id(&self.command_req_sender, &self.command_resp_receiver);
        if let Some(chain_id) = option {
            match chain_id {
                ChainId::V0(v0) => miscellaneous.set_chain_id(v0),
                ChainId::V1(v1) => miscellaneous.set_chain_id_v1(<[u8; 32]>::from(v1).to_vec()),
            }

            trace!("reply miscellaneous msg, chain_id: {:?}", chain_id);
        }

        let msg: Message = miscellaneous.into();
        self.response_mq(
            routing_key!(Executor >> Miscellaneous).into(),
            msg.try_into().unwrap(),
        );
    }

    fn reply_chain_request(&self, mut req: request::Request) {
        let mut response = response::Response::new();
        response.set_request_id(req.take_request_id());

        match req.req.unwrap() {
            Request::call(call) => {
                trace!("Chainvm Call {:?}", call);
                let _ = serde_json::from_str::<BlockNumber>(&call.height)
                    .map(|block_id| {
                        let call_request = CallRequest::from(call);
                        command::eth_call(
                            &self.command_req_sender,
                            &self.command_resp_receiver,
                            call_request,
                            block_id.into(),
                        )
                        .map(|ok| {
                            response.set_call_result(ok);
                        })
                        .map_err(|err| {
                            response.set_code(ErrorCode::query_error());
                            response.set_error_msg(err);
                        })
                    })
                    .map_err(|err| {
                        response.set_code(ErrorCode::query_error());
                        response.set_error_msg(format!("{:?}", err));
                    });
            }

            Request::transaction_count(tx_count) => {
                trace!("transaction count request from jsonrpc {:?}", tx_count);
                let _ = serde_json::from_str::<CountOrCode>(&tx_count)
                    .map_err(|err| {
                        response.set_code(ErrorCode::query_error());
                        response.set_error_msg(format!("{:?}", err));
                    })
                    .map(|tx_count| {
                        let address = Address::from_slice(tx_count.address.as_ref());
                        match command::nonce_at(
                            &self.command_req_sender,
                            &self.command_resp_receiver,
                            address,
                            tx_count.block_id.into(),
                        ) {
                            Some(nonce) => {
                                response.set_transaction_count(u64::from(nonce));
                            }
                            None => {
                                response.set_transaction_count(0);
                            }
                        };
                    });
            }

            Request::code(code_content) => {
                trace!("code request from jsonrpc  {:?}", code_content);
                let _ = serde_json::from_str::<CountOrCode>(&code_content)
                    .map_err(|err| {
                        response.set_code(ErrorCode::query_error());
                        response.set_error_msg(format!("{:?}", err));
                    })
                    .map(|code_content| {
                        let address = Address::from_slice(code_content.address.as_ref());
                        if let Some(code) = command::code_at(
                            &self.command_req_sender,
                            &self.command_resp_receiver,
                            address,
                            code_content.block_id.into(),
                        ) {
                            response.set_contract_code(code);
                        } else {
                            response.set_contract_code(vec![]);
                        };
                    });
            }

            Request::abi(abi_content) => {
                trace!("abi request from jsonrpc  {:?}", abi_content);
                let _ = serde_json::from_str::<CountOrCode>(&abi_content)
                    .map_err(|err| {
                        response.set_code(ErrorCode::query_error());
                        response.set_error_msg(format!("{:?}", err));
                    })
                    .map(|abi_content| {
                        let address = Address::from_slice(abi_content.address.as_ref());
                        if let Some(abi) = command::abi_at(
                            &self.command_req_sender,
                            &self.command_resp_receiver,
                            address,
                            abi_content.block_id.into(),
                        ) {
                            response.set_contract_abi(abi);
                        } else {
                            response.set_contract_abi(vec![]);
                        };
                    });
            }

            Request::balance(balance_content) => {
                trace!("balance request from jsonrpc  {:?}", balance_content);
                let _ = serde_json::from_str::<CountOrCode>(&balance_content)
                    .map_err(|err| {
                        response.set_code(ErrorCode::query_error());
                        response.set_error_msg(format!("{:?}", err));
                    })
                    .map(|balance_content| {
                        let address = Address::from_slice(balance_content.address.as_ref());
                        if let Some(balance) = command::balance_at(
                            &self.command_req_sender,
                            &self.command_resp_receiver,
                            address,
                            balance_content.block_id.into(),
                        ) {
                            response.set_balance(balance);
                        } else {
                            response.set_balance(vec![]);
                        };
                    });
            }

            Request::meta_data(data) => {
                match command::metadata(&self.command_req_sender, &self.command_resp_receiver, data)
                {
                    Ok(metadata) => {
                        response.set_meta_data(serde_json::to_string(&metadata).unwrap())
                    }
                    Err(error_msg) => {
                        response.set_code(ErrorCode::query_error());
                        response.set_error_msg(error_msg);
                    }
                }
            }

            Request::state_proof(state_info) => {
                trace!("state_proof info is {:?}", state_info);
                let _ = serde_json::from_str::<BlockNumber>(&state_info.height)
                    .map(|block_id| {
                        match command::state_at(
                            &self.command_req_sender,
                            &self.command_resp_receiver,
                            block_id.into(),
                        )
                        .and_then(|state| {
                            state.get_state_proof(
                                &Address::from(state_info.get_address()),
                                &H256::from(state_info.get_position()),
                            )
                        }) {
                            Some(state_proof_bs) => {
                                response.set_state_proof(state_proof_bs);
                            }
                            None => {
                                response.set_code(ErrorCode::query_error());
                                response.set_error_msg("get state proof failed".to_string());
                            }
                        }
                    })
                    .map_err(|err| {
                        response.set_code(ErrorCode::query_error());
                        response.set_error_msg(format!("{:?}", err));
                    });
            }
            Request::storage_key(skey) => {
                trace!("storage key info is {:?}", skey);
                let _ = serde_json::from_str::<BlockNumber>(&skey.height)
                    .map(|block_id| {
                        match command::state_at(
                            &self.command_req_sender,
                            &self.command_resp_receiver,
                            block_id.into(),
                        )
                        .and_then(|state| {
                            state
                                .storage_at(
                                    &Address::from(skey.get_address()),
                                    &H256::from(skey.get_position()),
                                )
                                .ok()
                        }) {
                            Some(storage_val) => {
                                response.set_storage_value(storage_val.to_vec());
                            }
                            None => {
                                response.set_code(ErrorCode::query_error());
                                response
                                    .set_error_msg("get storage at something failed".to_string());
                            }
                        }
                    })
                    .map_err(|err| {
                        response.set_code(ErrorCode::query_error());
                        response.set_error_msg(format!("{:?}", err));
                    });
            }

            _ => {
                error!("bad request msg!!!!");
            }
        };
        let msg: Message = response.into();
        self.response_mq(
            routing_key!(Executor >> Response).into(),
            msg.try_into().unwrap(),
        );
    }

    fn signal_to_chain(&self) {
        let mut state_signal = StateSignal::new();
        state_signal.set_height(self.get_current_height());
        let msg: Message = state_signal.into();
        self.response_mq(
            routing_key!(Executor >> StateSignal).into(),
            msg.try_into().unwrap(),
        );
    }

    fn get_current_height(&self) -> u64 {
        self.backlogs.get_current_height()
    }

    fn response_mq(&self, key: String, message: Vec<u8>) {
        trace!("send {} into RabbitMQ", key);
        self.mq_resp_sender.send((key, message));
    }
}

// System Convention: 0-th block's proof is `::std::usize::MAX`
fn wrap_height(height: usize) -> u64 {
    match height {
        ::std::usize::MAX => 0,
        _ => height as u64,
    }
}

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

    #[test]
    fn test_wrap_height() {
        assert_eq!(0, wrap_height(::std::usize::MAX));
        assert_eq!(::std::usize::MAX as u64 - 1, wrap_height(::std::usize::MAX - 1));
        assert_eq!(2, wrap_height(2));
    }
}<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use chrono::naive::NaiveDateTime;
use toml_query::delete::TomlValueDeleteExt;
use toml_query::insert::TomlValueInsertExt;
use toml_query::read::TomlValueReadExt;
use toml::Value;

use libimagstore::store::Entry;

use error::DateErrorKind as DEK;
use error::DateError as DE;
use error::*;
use range::DateTimeRange;

pub trait EntryDate {

    fn delete_date(&mut self) -> Result<()>;
    fn read_date(&self) -> Result<NaiveDateTime>;
    fn set_date(&mut self, d: NaiveDateTime) -> Result<Option<Result<NaiveDateTime>>>;

    fn delete_date_range(&mut self) -> Result<()>;
    fn read_date_range(&self) -> Result<DateTimeRange>;
    fn set_date_range(&mut self, start: NaiveDateTime, end: NaiveDateTime) -> Result<Option<Result<DateTimeRange>>>;

}

lazy_static! {
    static ref DATE_HEADER_LOCATION : &'static str              = "datetime.value";
    static ref DATE_RANGE_START_HEADER_LOCATION : &'static str  = "datetime.range.start";
    static ref DATE_RANGE_END_HEADER_LOCATION : &'static str    = "datetime.range.end";
    static ref DATE_FMT : &'static str                          = "%Y-%m-%dT%H:%M:%S";
}

impl EntryDate for Entry {

    fn delete_date(&mut self) -> Result<()> {
        self.get_header_mut()
            .delete(&DATE_HEADER_LOCATION)
            .map(|_| ())
            .chain_err(|| DEK::DeleteDateError)
    }

    fn read_date(&self) -> Result<NaiveDateTime> {
        self.get_header()
            .read(&DATE_HEADER_LOCATION)
            .chain_err(|| DEK::ReadDateError)
            .and_then(|v| {
                match v {
                    Some(&Value::String(ref s)) => s.parse::<NaiveDateTime>()
                        .chain_err(|| DEK::DateTimeParsingError),
                    Some(_) => Err(DE::from_kind(DEK::DateHeaderFieldTypeError)),
                    _ => Err(DE::from_kind(DEK::ReadDateError)),
                }
            })
    }

    /// Set a Date for this entry
    ///
    /// # Return value
    ///
    /// This function returns funny things, I know. But I find it more attractive to be explicit
    /// what failed when here, instead of beeing nice to the user here.
    ///
    /// So here's a list how things are returned:
    ///
    /// - Err(_) if the inserting failed
    /// - Ok(None) if the inserting succeeded and _did not replace an existing value_.
    /// - Ok(Some(Ok(_))) if the inserting succeeded, but replaced an existing value which then got
    /// parsed into a NaiveDateTime object
    /// - Ok(Some(Err(_))) if the inserting succeeded, but replaced an existing value which then
    /// got parsed into a NaiveDateTime object, where the parsing failed for some reason.
    ///
    fn set_date(&mut self, d: NaiveDateTime) -> Result<Option<Result<NaiveDateTime>>> {
        let date = d.format(&DATE_FMT).to_string();

        self.get_header_mut()
            .insert(&DATE_HEADER_LOCATION, Value::String(date))
            .map(|opt| opt.map(|stri| {
                match stri {
                    Value::String(ref s) => s.parse::<NaiveDateTime>()
                                             .chain_err(|| DEK::DateTimeParsingError),
                    _ => Err(DE::from_kind(DEK::DateHeaderFieldTypeError)),
                }
            }))
            .chain_err(|| DEK::SetDateError)
    }

    /// Deletes the date range
    ///
    /// # Warning
    ///
    /// First deletes the start, then the end. If the first operation fails, this might leave the
    /// header in an inconsistent state.
    ///
    fn delete_date_range(&mut self) -> Result<()> {
        let _ = self
             .get_header_mut()
            .delete(&DATE_RANGE_START_HEADER_LOCATION)
            .map(|_| ())
            .chain_err(|| DEK::DeleteDateTimeRangeError)?;

        self.get_header_mut()
            .delete(&DATE_RANGE_END_HEADER_LOCATION)
            .map(|_| ())
            .chain_err(|| DEK::DeleteDateTimeRangeError)
    }

    fn read_date_range(&self) -> Result<DateTimeRange> {
        let start = self
            .get_header()
            .read(&DATE_RANGE_START_HEADER_LOCATION)
            .chain_err(|| DEK::ReadDateTimeRangeError)
            .and_then(|v| {
                match v {
                    Some(&Value::String(ref s)) => s.parse::<NaiveDateTime>()
                        .chain_err(|| DEK::DateTimeParsingError),
                    Some(_) => Err(DE::from_kind(DEK::DateHeaderFieldTypeError)),
                    _ => Err(DE::from_kind(DEK::ReadDateError)),
                }
            })?;

        let end = self
            .get_header()
            .read(&DATE_RANGE_START_HEADER_LOCATION)
            .chain_err(|| DEK::ReadDateTimeRangeError)
            .and_then(|v| {
                match v {
                    Some(&Value::String(ref s)) => s.parse::<NaiveDateTime>()
                        .chain_err(|| DEK::DateTimeParsingError),
                    Some(_) => Err(DE::from_kind(DEK::DateHeaderFieldTypeError)),
                    _ => Err(DE::from_kind(DEK::ReadDateError)),
                }
            })?;

        DateTimeRange::new(start, end)
            .chain_err(|| DEK::DateTimeRangeError)
    }

    /// Set the date range
    ///
    /// # Warning
    ///
    /// This first sets the start, then the end. If the first operation fails, this might leave the
    /// header in an inconsistent state.
    ///
    fn set_date_range(&mut self, start: NaiveDateTime, end: NaiveDateTime)
        -> Result<Option<Result<DateTimeRange>>>
    {
        let start = start.format(&DATE_FMT).to_string();
        let end   = end.format(&DATE_FMT).to_string();

        let opt_old_start = self
            .get_header_mut()
            .insert(&DATE_RANGE_START_HEADER_LOCATION, Value::String(start))
            .map(|opt| opt.map(|stri| {
                match stri {
                    Value::String(ref s) => s.parse::<NaiveDateTime>()
                                             .chain_err(|| DEK::DateTimeParsingError),
                    _ => Err(DE::from_kind(DEK::DateHeaderFieldTypeError)),
                }
            }))
            .chain_err(|| DEK::SetDateTimeRangeError)?;

        let opt_old_end = self
            .get_header_mut()
            .insert(&DATE_RANGE_END_HEADER_LOCATION, Value::String(end))
            .map(|opt| opt.map(|stri| {
                match stri {
                    Value::String(ref s) => s.parse::<NaiveDateTime>()
                                             .chain_err(|| DEK::DateTimeParsingError),
                    _ => Err(DE::from_kind(DEK::DateHeaderFieldTypeError)),
                }
            }))
            .chain_err(|| DEK::SetDateTimeRangeError)?;

        match (opt_old_start, opt_old_end) {
            (Some(Ok(old_start)), Some(Ok(old_end))) => {
                let dr = DateTimeRange::new(old_start, old_end)
                    .chain_err(|| DEK::DateTimeRangeError);

                Ok(Some(dr))
            },

            (Some(Err(e)), _) => Err(e),
            (_, Some(Err(e))) => Err(e),
            _ => {
                Ok(None)
            },
        }
    }

}

#[cfg(test)]
mod tests {
    use std::path::PathBuf;

    use super::*;

    use libimagstore::store::Store;

    use chrono::naive::NaiveDateTime;
    use chrono::naive::NaiveDate;
    use chrono::naive::NaiveTime;

    pub fn get_store() -> Store {
        use libimagstore::store::InMemoryFileAbstraction;
        let backend = Box::new(InMemoryFileAbstraction::new());
        Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap()
    }

    #[test]
    fn test_set_date() {
        let store = get_store();

        let date = {
            let date = NaiveDate::from_ymd(2000, 01, 02);
            let time = NaiveTime::from_hms(03, 04, 05);

            NaiveDateTime::new(date, time)
        };

        let mut entry   = store.create(PathBuf::from("test")).unwrap();
        let res         = entry.set_date(date);

        assert!(res.is_ok(), format!("Error: {:?}", res));
        let res = res.unwrap();

        assert!(res.is_none()); // There shouldn't be an existing value

        // Check whether the header is set correctly

        let hdr_field = entry.get_header().read(&DATE_HEADER_LOCATION);

        assert!(hdr_field.is_ok());
        let hdr_field = hdr_field.unwrap();

        assert!(hdr_field.is_some());
        let hdr_field = hdr_field.unwrap();

        match *hdr_field {
            Value::String(ref s) => assert_eq!("2000-01-02T03:04:05", s),
            _ => assert!(false, "Wrong header type"),
        }
    }

    #[test]
    fn test_read_date() {
        use chrono::Datelike;
        use chrono::Timelike;

        let store = get_store();

        let date = {
            let date = NaiveDate::from_ymd(2000, 01, 02);
            let time = NaiveTime::from_hms(03, 04, 05);

            NaiveDateTime::new(date, time)
        };

        let mut entry   = store.create(PathBuf::from("test")).unwrap();
        let res         = entry.set_date(date);

        assert!(res.is_ok(), format!("Expected Ok(_), got: {:?}", res));
        let res = res.unwrap();

        assert!(res.is_none()); // There shouldn't be an existing value

        // same as the test above ...

        let d = entry.read_date();

        assert!(d.is_ok(), format!("Expected Ok(_), got: {:?}", d));
        let d = d.unwrap();

        assert_eq!(d.date().year()   , 2000);
        assert_eq!(d.date().month()  ,   01);
        assert_eq!(d.date().day()    ,   02);
        assert_eq!(d.time().hour()   ,   03);
        assert_eq!(d.time().minute() ,   04);
        assert_eq!(d.time().second() ,   05);
    }

    #[test]
    fn test_delete_date() {
        let store = get_store();

        let date = {
            let date = NaiveDate::from_ymd(2000, 01, 02);
            let time = NaiveTime::from_hms(03, 04, 05);

            NaiveDateTime::new(date, time)
        };

        let mut entry   = store.create(PathBuf::from("test")).unwrap();
        let res         = entry.set_date(date);

        assert!(res.is_ok(), format!("Expected Ok(_), got: {:?}", res));
        let res = res.unwrap();
        assert!(res.is_none()); // There shouldn't be an existing value

        assert!(entry.delete_date().is_ok());

        let hdr_field = entry.get_header().read(&DATE_HEADER_LOCATION);

        assert!(hdr_field.is_ok());
        let hdr_field = hdr_field.unwrap();

        assert!(hdr_field.is_none());
    }
}

<commit_msg>Refactor: Use function chaining rather than matching<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use chrono::naive::NaiveDateTime;
use toml_query::delete::TomlValueDeleteExt;
use toml_query::insert::TomlValueInsertExt;
use toml_query::read::TomlValueReadExt;
use toml::Value;

use libimagstore::store::Entry;

use error::DateErrorKind as DEK;
use error::DateError as DE;
use error::*;
use range::DateTimeRange;

pub trait EntryDate {

    fn delete_date(&mut self) -> Result<()>;
    fn read_date(&self) -> Result<NaiveDateTime>;
    fn set_date(&mut self, d: NaiveDateTime) -> Result<Option<Result<NaiveDateTime>>>;

    fn delete_date_range(&mut self) -> Result<()>;
    fn read_date_range(&self) -> Result<DateTimeRange>;
    fn set_date_range(&mut self, start: NaiveDateTime, end: NaiveDateTime) -> Result<Option<Result<DateTimeRange>>>;

}

lazy_static! {
    static ref DATE_HEADER_LOCATION : &'static str              = "datetime.value";
    static ref DATE_RANGE_START_HEADER_LOCATION : &'static str  = "datetime.range.start";
    static ref DATE_RANGE_END_HEADER_LOCATION : &'static str    = "datetime.range.end";
    static ref DATE_FMT : &'static str                          = "%Y-%m-%dT%H:%M:%S";
}

impl EntryDate for Entry {

    fn delete_date(&mut self) -> Result<()> {
        self.get_header_mut()
            .delete(&DATE_HEADER_LOCATION)
            .map(|_| ())
            .chain_err(|| DEK::DeleteDateError)
    }

    fn read_date(&self) -> Result<NaiveDateTime> {
        self.get_header()
            .read(&DATE_HEADER_LOCATION)
            .chain_err(|| DEK::ReadDateError)
            .and_then(|v| {
                v.ok_or(DE::from_kind(DEK::ReadDateError))?
                    .as_str()
                    .ok_or(DE::from_kind(DEK::DateHeaderFieldTypeError))?
                    .parse::<NaiveDateTime>()
                    .chain_err(|| DEK::DateTimeParsingError)
            })
    }

    /// Set a Date for this entry
    ///
    /// # Return value
    ///
    /// This function returns funny things, I know. But I find it more attractive to be explicit
    /// what failed when here, instead of beeing nice to the user here.
    ///
    /// So here's a list how things are returned:
    ///
    /// - Err(_) if the inserting failed
    /// - Ok(None) if the inserting succeeded and _did not replace an existing value_.
    /// - Ok(Some(Ok(_))) if the inserting succeeded, but replaced an existing value which then got
    /// parsed into a NaiveDateTime object
    /// - Ok(Some(Err(_))) if the inserting succeeded, but replaced an existing value which then
    /// got parsed into a NaiveDateTime object, where the parsing failed for some reason.
    ///
    fn set_date(&mut self, d: NaiveDateTime) -> Result<Option<Result<NaiveDateTime>>> {
        let date = d.format(&DATE_FMT).to_string();

        self.get_header_mut()
            .insert(&DATE_HEADER_LOCATION, Value::String(date))
            .map(|opt| opt.map(|stri| {
                stri.as_str()
                    .ok_or(DE::from_kind(DEK::DateHeaderFieldTypeError))?
                    .parse::<NaiveDateTime>()
                    .chain_err(|| DEK::DateTimeParsingError)
            }))
            .chain_err(|| DEK::SetDateError)
    }

    /// Deletes the date range
    ///
    /// # Warning
    ///
    /// First deletes the start, then the end. If the first operation fails, this might leave the
    /// header in an inconsistent state.
    ///
    fn delete_date_range(&mut self) -> Result<()> {
        let _ = self
             .get_header_mut()
            .delete(&DATE_RANGE_START_HEADER_LOCATION)
            .map(|_| ())
            .chain_err(|| DEK::DeleteDateTimeRangeError)?;

        self.get_header_mut()
            .delete(&DATE_RANGE_END_HEADER_LOCATION)
            .map(|_| ())
            .chain_err(|| DEK::DeleteDateTimeRangeError)
    }

    fn read_date_range(&self) -> Result<DateTimeRange> {
        let start = self
            .get_header()
            .read(&DATE_RANGE_START_HEADER_LOCATION)
            .chain_err(|| DEK::ReadDateTimeRangeError)
            .and_then(|v| str_to_ndt(v.ok_or(DE::from_kind(DEK::ReadDateError))?))?;

        let end = self
            .get_header()
            .read(&DATE_RANGE_START_HEADER_LOCATION)
            .chain_err(|| DEK::ReadDateTimeRangeError)
            .and_then(|v| str_to_ndt(v.ok_or(DE::from_kind(DEK::ReadDateError))?))?;

        DateTimeRange::new(start, end).chain_err(|| DEK::DateTimeRangeError)
    }

    /// Set the date range
    ///
    /// # Warning
    ///
    /// This first sets the start, then the end. If the first operation fails, this might leave the
    /// header in an inconsistent state.
    ///
    fn set_date_range(&mut self, start: NaiveDateTime, end: NaiveDateTime)
        -> Result<Option<Result<DateTimeRange>>>
    {
        let start = start.format(&DATE_FMT).to_string();
        let end   = end.format(&DATE_FMT).to_string();

        let opt_old_start = self
            .get_header_mut()
            .insert(&DATE_RANGE_START_HEADER_LOCATION, Value::String(start))
            .map(|opt| opt.as_ref().map(str_to_ndt))
            .chain_err(|| DEK::SetDateTimeRangeError)?;

        let opt_old_end = self
            .get_header_mut()
            .insert(&DATE_RANGE_END_HEADER_LOCATION, Value::String(end))
            .map(|opt| opt.as_ref().map(str_to_ndt))
            .chain_err(|| DEK::SetDateTimeRangeError)?;

        match (opt_old_start, opt_old_end) {
            (Some(Ok(old_start)), Some(Ok(old_end))) => {
                let dr = DateTimeRange::new(old_start, old_end)
                    .chain_err(|| DEK::DateTimeRangeError);

                Ok(Some(dr))
            },

            (Some(Err(e)), _) => Err(e),
            (_, Some(Err(e))) => Err(e),
            _ => {
                Ok(None)
            },
        }
    }

}

fn str_to_ndt(v: &Value) -> Result<NaiveDateTime> {
    v.as_str()
        .ok_or(DE::from_kind(DEK::DateHeaderFieldTypeError))?
        .parse::<NaiveDateTime>()
        .chain_err(|| DEK::DateTimeParsingError)
}

#[cfg(test)]
mod tests {
    use std::path::PathBuf;

    use super::*;

    use libimagstore::store::Store;

    use chrono::naive::NaiveDateTime;
    use chrono::naive::NaiveDate;
    use chrono::naive::NaiveTime;

    pub fn get_store() -> Store {
        use libimagstore::store::InMemoryFileAbstraction;
        let backend = Box::new(InMemoryFileAbstraction::new());
        Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap()
    }

    #[test]
    fn test_set_date() {
        let store = get_store();

        let date = {
            let date = NaiveDate::from_ymd(2000, 01, 02);
            let time = NaiveTime::from_hms(03, 04, 05);

            NaiveDateTime::new(date, time)
        };

        let mut entry   = store.create(PathBuf::from("test")).unwrap();
        let res         = entry.set_date(date);

        assert!(res.is_ok(), format!("Error: {:?}", res));
        let res = res.unwrap();

        assert!(res.is_none()); // There shouldn't be an existing value

        // Check whether the header is set correctly

        let hdr_field = entry.get_header().read(&DATE_HEADER_LOCATION);

        assert!(hdr_field.is_ok());
        let hdr_field = hdr_field.unwrap();

        assert!(hdr_field.is_some());
        let hdr_field = hdr_field.unwrap();

        match *hdr_field {
            Value::String(ref s) => assert_eq!("2000-01-02T03:04:05", s),
            _ => assert!(false, "Wrong header type"),
        }
    }

    #[test]
    fn test_read_date() {
        use chrono::Datelike;
        use chrono::Timelike;

        let store = get_store();

        let date = {
            let date = NaiveDate::from_ymd(2000, 01, 02);
            let time = NaiveTime::from_hms(03, 04, 05);

            NaiveDateTime::new(date, time)
        };

        let mut entry   = store.create(PathBuf::from("test")).unwrap();
        let res         = entry.set_date(date);

        assert!(res.is_ok(), format!("Expected Ok(_), got: {:?}", res));
        let res = res.unwrap();

        assert!(res.is_none()); // There shouldn't be an existing value

        // same as the test above ...

        let d = entry.read_date();

        assert!(d.is_ok(), format!("Expected Ok(_), got: {:?}", d));
        let d = d.unwrap();

        assert_eq!(d.date().year()   , 2000);
        assert_eq!(d.date().month()  ,   01);
        assert_eq!(d.date().day()    ,   02);
        assert_eq!(d.time().hour()   ,   03);
        assert_eq!(d.time().minute() ,   04);
        assert_eq!(d.time().second() ,   05);
    }

    #[test]
    fn test_delete_date() {
        let store = get_store();

        let date = {
            let date = NaiveDate::from_ymd(2000, 01, 02);
            let time = NaiveTime::from_hms(03, 04, 05);

            NaiveDateTime::new(date, time)
        };

        let mut entry   = store.create(PathBuf::from("test")).unwrap();
        let res         = entry.set_date(date);

        assert!(res.is_ok(), format!("Expected Ok(_), got: {:?}", res));
        let res = res.unwrap();
        assert!(res.is_none()); // There shouldn't be an existing value

        assert!(entry.delete_date().is_ok());

        let hdr_field = entry.get_header().read(&DATE_HEADER_LOCATION);

        assert!(hdr_field.is_ok());
        let hdr_field = hdr_field.unwrap();

        assert!(hdr_field.is_none());
    }
}

<|endoftext|>


<commit_before>use arch::memory;

use system::error::Result;

//TODO: Refactor file to propogate results

pub fn do_sys_brk(addr: usize) -> Result<usize> {
    let mut ret = 0;

    let mut contexts = ::env().contexts.lock();
    if let Ok(mut current) = contexts.current_mut() {
        unsafe {
            current.unmap();
        }

        ret = current.next_mem();

        // TODO: Make this smarter, currently it attempt to resize the entire data segment
        if let Some(mut mem) = unsafe { (*current.memory.get()).last_mut() } {
            if mem.writeable && mem.allocated {
                if addr >= mem.virtual_address {
                    let size = addr - mem.virtual_address;
                    let physical_address = unsafe { memory::realloc(mem.physical_address, size) };
                    if physical_address > 0 {
                        mem.physical_address = physical_address;
                        mem.virtual_size = size;
                        ret = mem.virtual_address + mem.virtual_size;
                    } else {
                        mem.virtual_size = 0;
                        debug!("BRK: Realloc failed {:X}, {}\n", mem.virtual_address, size);
                    }
                }
            } else {
                debug!("BRK: End segment not writeable or allocated\n");
            }
        } else {
            debug!("BRK: No segments\n")
        }

        unsafe {
            current.clean_mem();
            current.map();
        }
    } else {
        debug!("BRK: Context not found\n");
    }

    Ok(ret)
}
<commit_msg>Fixes for brk<commit_after>use arch::memory;

use system::error::Result;

//TODO: Refactor file to propogate results

pub fn do_sys_brk(addr: usize) -> Result<usize> {
    let mut ret = 0;

    let contexts = ::env().contexts.lock();
    if let Ok(current) = contexts.current() {
        ret = current.next_mem();

        // TODO: Make this smarter, currently it attempt to resize the entire data segment
        if let Some(mut mem) = unsafe { (*current.memory.get()).last_mut() } {
            if mem.writeable && mem.allocated {
                if addr >= mem.virtual_address {
                    unsafe { mem.unmap() };

                    let size = addr - mem.virtual_address;
                    let physical_address = unsafe { memory::realloc(mem.physical_address, size) };
                    if physical_address > 0 {
                        mem.physical_address = physical_address;
                        mem.virtual_size = size;
                        ret = mem.virtual_address + mem.virtual_size;
                    } else {
                        mem.virtual_size = 0;
                        debugln!("BRK: Realloc failed {:X}, {}\n", mem.virtual_address, size);
                    }

                    unsafe { mem.map() };
                }
            } else {
                debugln!("{:X}: {}", current.pid, current.name);
                debugln!("BRK: End segment not writeable or allocated");
            }
        } else {
            debugln!("BRK: No segments");
        }
    } else {
        debugln!("BRK: Context not found");
    }

    Ok(ret)
}
<|endoftext|>


<commit_before><commit_msg>Do not use deprecated way of checking whether path exists<commit_after><|endoftext|>


<commit_before><commit_msg>add number example<commit_after>#[macro_use]
extern crate generator;
use generator::*;

fn factors(n: u32) -> Generator<'static, (), u32> {
    Gn::new_scoped(move |mut s| {
        if n == 0 {
            return 0;
        }

        s.yield_with(1);

        for i in 2..n {
            if n % i == 0 {
                s.yield_with(i);
            }
        }
        done!();
    })
}

fn main() {
    for i in factors(28) {
        println!("{}", i);
    }

    (0..10000).filter(|n| factors(*n).sum::<u32>() == *n).fold((), |_, n| {
        println!("n = {}", n);
    })
}
<|endoftext|>


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

// Coroutines represent nothing more than a context and a stack
// segment.

use std::default::Default;
use std::rt::util::min_stack;
use thunk::Thunk;
use std::mem::{transmute, transmute_copy};
use std::rt::unwind::try;
use std::any::Any;
use std::cell::UnsafeCell;
use std::ops::DerefMut;
use std::ptr;

use context::Context;
use stack::{StackPool, Stack};

#[derive(Debug, Copy)]
pub enum State {
    Suspended,
    Running,
    Finished,
    Panicked,
}

pub type ResumeResult<T> = Result<T, Box<Any + Send>>;

/// Coroutine spawn options
#[derive(Debug)]
pub struct Options {
    pub stack_size: usize,
    pub name: Option<String>,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            stack_size: min_stack(),
            name: None,
        }
    }
}

/// Handle of a Coroutine
#[derive(Debug)]
pub struct Handle(Box<Coroutine>);

impl Handle {

    #[inline]
    pub fn state(&self) -> State {
        self.0.state()
    }

    pub fn resume(mut self) -> ResumeResult<Handle> {
        match self.state() {
            State::Finished | State::Running => return Ok(self),
            State::Panicked => panic!("Tried to resume a panicked coroutine"),
            _ => {}
        }

        COROUTINE_ENVIRONMENT.with(|env| {
            let env: &mut Environment = unsafe { transmute(env.get()) };

            // Move out, keep this reference
            // It may not be the only reference to the Coroutine
            //
            let mut from_coro = env.current_running.take().unwrap();

            // Save state
            self.0.state = State::Running;
            self.0.parent = from_coro.0.deref_mut();
            from_coro.0.state = State::Suspended;

            // Move inside the Environment
            env.current_running = Some(self);

            Context::swap(&mut from_coro.0.saved_context, &env.current_running.as_ref().unwrap().0.saved_context);

            // Move out here
            self = env.current_running.take().unwrap();
            env.current_running = Some(from_coro);

            match env.running_state.take() {
                Some(err) => {
                    Err(err)
                },
                None => {
                    Ok(self)
                }
            }
        })
    }

    #[inline]
    pub fn join(self) -> ResumeResult<Handle> {
        let mut coro = self;
        loop {
            match coro.state() {
                State::Suspended => coro = try!(coro.resume()),
                _ => break,
            }
        }
        Ok(coro)
    }
}

/// A coroutine is nothing more than a (register context, stack) pair.
#[allow(raw_pointer_derive)]
#[derive(Debug)]
pub struct Coroutine {
    /// The segment of stack on which the task is currently running or
    /// if the task is blocked, on which the task will resume
    /// execution.
    current_stack_segment: Option<Stack>,

    /// Always valid if the task is alive and not running.
    saved_context: Context,

    /// Parent coroutine, will always be valid
    parent: *mut Coroutine,

    /// State
    state: State,

    /// Name
    name: Option<String>,
}

unsafe impl Send for Coroutine {}
unsafe impl Sync for Coroutine {}

/// Destroy coroutine and try to reuse std::stack segment.
impl Drop for Coroutine {
    fn drop(&mut self) {
        match self.current_stack_segment.take() {
            Some(stack) => {
                COROUTINE_ENVIRONMENT.with(|env| {
                    let env: &mut Environment = unsafe { transmute(env.get()) };
                    env.stack_pool.give_stack(stack);
                });
            },
            None => {}
        }
    }
}

/// Initialization function for make context
extern "C" fn coroutine_initialize(_: usize, f: *mut ()) -> ! {
    let func: Box<Thunk> = unsafe { transmute(f) };

    let ret = unsafe { try(move|| func.invoke(())) };

    COROUTINE_ENVIRONMENT.with(move|env| {
        let env: &mut Environment = unsafe { transmute(env.get()) };

        match ret {
            Ok(..) => {
                env.running_state = None;
                env.current_running.as_mut().unwrap().0.state = State::Finished;
            }
            Err(err) => {
                env.running_state = Some(err);
                env.current_running.as_mut().unwrap().0.state = State::Panicked;
            }
        }
    });

    loop {
        Coroutine::sched();
    }
}

impl Coroutine {
    pub fn empty() -> Handle {
        Handle(box Coroutine {
            current_stack_segment: None,
            saved_context: Context::empty(),
            parent: ptr::null_mut(),
            state: State::Running,
            name: None,
        })
    }

    pub fn with_name(name: &str) -> Handle {
        Handle(box Coroutine {
            current_stack_segment: None,
            saved_context: Context::empty(),
            parent: ptr::null_mut(),
            state: State::Running,
            name: Some(name.to_string()),
        })
    }

    pub fn spawn_opts<F>(f: F, opts: Options) -> Handle
            where F: FnOnce() + Send + 'static {

        let coro = UnsafeCell::new(Coroutine::empty());
        COROUTINE_ENVIRONMENT.with(|env| {
            unsafe {
                let env: &mut Environment = transmute(env.get());

                let mut stack = env.stack_pool.take_stack(opts.stack_size);

                let ctx = Context::new(coroutine_initialize,
                                   0,
                                   f,
                                   &mut stack);

                let coro: &mut Handle = transmute(coro.get());
                coro.0.saved_context = ctx;
                coro.0.current_stack_segment = Some(stack);
                coro.0.state = State::Suspended;
            }
        });

        let mut coro = unsafe { coro.into_inner() };
        coro.0.name = opts.name;
        coro
    }

    /// Spawn a coroutine with default options
    pub fn spawn<F>(f: F) -> Handle
            where F: FnOnce() + Send + 'static {
        Coroutine::spawn_opts(f, Default::default())
    }

    pub fn sched() {
        COROUTINE_ENVIRONMENT.with(|env| {
            let env: &mut Environment = unsafe { transmute(env.get()) };

            // Move out
            let mut from_coro = env.current_running.as_mut().unwrap();

            match from_coro.state() {
                State::Finished | State::Panicked => {},
                _ => from_coro.0.state = State::Suspended,
            }

            let to_coro: &mut Coroutine = unsafe { transmute_copy(&from_coro.0.parent) };

            Context::swap(&mut from_coro.0.saved_context, &to_coro.saved_context);
        });
    }

    pub fn current() -> HandleGuard {
        HandleGuard
    }

    pub fn state(&self) -> State {
        self.state
    }
}

pub struct HandleGuard;

impl HandleGuard {
    pub fn with<F>(&self, f: F)
            where F: FnOnce(Handle) -> Handle + Send + 'static {
        COROUTINE_ENVIRONMENT.with(|env| {
            let env: &mut Environment = unsafe { transmute(env.get()) };
            env.current_running = Some(f(env.current_running.take().unwrap()));
        });
    }
}

thread_local!(static COROUTINE_ENVIRONMENT: UnsafeCell<Environment> = UnsafeCell::new(Environment::new()));

/// Coroutine managing environment
#[allow(raw_pointer_derive)]
#[derive(Debug)]
struct Environment {
    stack_pool: StackPool,
    current_running: Option<Handle>,

    running_state: Option<Box<Any + Send>>,
}

impl Environment {
    /// Initialize a new environment
    fn new() -> Environment {
        let mut coro = Coroutine::with_name("<Environment Root Coroutine>");
        coro.0.parent = coro.0.deref_mut(); // Pointing to itself

        Environment {
            stack_pool: StackPool::new(),
            current_running: Some(coro),

            running_state: None,
        }
    }
}

#[cfg(test)]
mod test {
    use std::sync::mpsc::channel;

    use test::Bencher;

    use coroutine::Coroutine;

    #[test]
    fn test_coroutine_basic() {
        let (tx, rx) = channel();
        Coroutine::spawn(move|| {
            tx.send(1).unwrap();
        }).resume().unwrap();

        assert_eq!(rx.recv().unwrap(), 1);
    }

    #[test]
    fn test_coroutine_yield() {
        let (tx, rx) = channel();
        let coro = Coroutine::spawn(move|| {
            tx.send(1).unwrap();

            Coroutine::sched();

            tx.send(2).unwrap();
        }).resume().unwrap();
        assert_eq!(rx.recv().unwrap(), 1);
        assert!(rx.try_recv().is_err());

        coro.resume().unwrap();

        assert_eq!(rx.recv().unwrap(), 2);
    }

    #[test]
    fn test_coroutine_spawn_inside() {
        let (tx, rx) = channel();
        Coroutine::spawn(move|| {
            tx.send(1).unwrap();

            Coroutine::spawn(move|| {
                tx.send(2).unwrap();
            }).join().unwrap();

        }).join().unwrap();;

        assert_eq!(rx.recv().unwrap(), 1);
        assert_eq!(rx.recv().unwrap(), 2);
    }

    #[test]
    fn test_coroutine_panic() {
        let coro = Coroutine::spawn(move|| {
            panic!("Panic inside a coroutine!!");
        });
        assert!(coro.join().is_err());
    }

    #[test]
    fn test_coroutine_child_panic() {
        Coroutine::spawn(move|| {
            let _ = Coroutine::spawn(move|| {
                panic!("Panic inside a coroutine's child!!");
            }).join();
        }).join().unwrap();
    }

    #[test]
    fn test_coroutine_resume_after_finished() {
        let mut coro = Coroutine::spawn(move|| {});

        // It is already finished, but we try to resume it
        // Idealy it would come back immediately
        coro = coro.resume().unwrap();

        // Again?
        assert!(coro.resume().is_ok());
    }

    #[test]
    fn test_coroutine_resume_itself() {
        let coro = Coroutine::spawn(move|| {
            // Resume itself
            Coroutine::current().with(|me| {
                me.resume().unwrap()
            });
        });

        assert!(coro.resume().is_ok());
    }

    #[test]
    fn test_coroutine_yield_in_main() {
        Coroutine::sched();
    }

    #[bench]
    fn bench_coroutine_spawning_with_recycle(b: &mut Bencher) {
        b.iter(|| {
            let _ = Coroutine::spawn(move|| {}).resume();
        });
    }

    #[bench]
    fn bench_normal_counting(b: &mut Bencher) {
        b.iter(|| {
            const MAX_NUMBER: usize = 100;

            let (tx, rx) = channel();

            let mut result = 0;
            for _ in 0..MAX_NUMBER {
                tx.send(1).unwrap();
                result += rx.recv().unwrap();
            }
            assert_eq!(result, MAX_NUMBER);
        });
    }

    #[bench]
    fn bench_coroutine_counting(b: &mut Bencher) {
        b.iter(|| {
            const MAX_NUMBER: usize = 100;
            let (tx, rx) = channel();

            let mut coro = Coroutine::spawn(move|| {
                for _ in 0..MAX_NUMBER {
                    tx.send(1).unwrap();
                    Coroutine::sched();
                }
            }).resume().unwrap();;

            let mut result = 0;
            for n in rx.iter() {
                coro = coro.resume().unwrap();
                result += n;
            }
            assert_eq!(result, MAX_NUMBER);
        });
    }
}
<commit_msg>remove some unsafeCell<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Coroutines represent nothing more than a context and a stack
// segment.

use std::default::Default;
use std::rt::util::min_stack;
use thunk::Thunk;
use std::mem::{transmute, transmute_copy};
use std::rt::unwind::try;
use std::any::Any;
use std::cell::UnsafeCell;
use std::ops::DerefMut;
use std::ptr;

use context::Context;
use stack::{StackPool, Stack};

#[derive(Debug, Copy)]
pub enum State {
    Suspended,
    Running,
    Finished,
    Panicked,
}

pub type ResumeResult<T> = Result<T, Box<Any + Send>>;

/// Coroutine spawn options
#[derive(Debug)]
pub struct Options {
    pub stack_size: usize,
    pub name: Option<String>,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            stack_size: min_stack(),
            name: None,
        }
    }
}

/// Handle of a Coroutine
#[derive(Debug)]
pub struct Handle(Box<Coroutine>);

impl Handle {

    #[inline]
    pub fn state(&self) -> State {
        self.0.state()
    }

    pub fn resume(mut self) -> ResumeResult<Handle> {
        match self.state() {
            State::Finished | State::Running => return Ok(self),
            State::Panicked => panic!("Tried to resume a panicked coroutine"),
            _ => {}
        }

        COROUTINE_ENVIRONMENT.with(|env| {
            let env: &mut Environment = unsafe { transmute(env.get()) };

            // Move out, keep this reference
            // It may not be the only reference to the Coroutine
            //
            let mut from_coro = env.current_running.take().unwrap();

            // Save state
            self.0.state = State::Running;
            self.0.parent = from_coro.0.deref_mut();
            from_coro.0.state = State::Suspended;

            // Move inside the Environment
            env.current_running = Some(self);

            Context::swap(&mut from_coro.0.saved_context, &env.current_running.as_ref().unwrap().0.saved_context);

            // Move out here
            self = env.current_running.take().unwrap();
            env.current_running = Some(from_coro);

            match env.running_state.take() {
                Some(err) => {
                    Err(err)
                },
                None => {
                    Ok(self)
                }
            }
        })
    }

    #[inline]
    pub fn join(self) -> ResumeResult<Handle> {
        let mut coro = self;
        loop {
            match coro.state() {
                State::Suspended => coro = try!(coro.resume()),
                _ => break,
            }
        }
        Ok(coro)
    }
}

/// A coroutine is nothing more than a (register context, stack) pair.
#[allow(raw_pointer_derive)]
#[derive(Debug)]
pub struct Coroutine {
    /// The segment of stack on which the task is currently running or
    /// if the task is blocked, on which the task will resume
    /// execution.
    current_stack_segment: Option<Stack>,

    /// Always valid if the task is alive and not running.
    saved_context: Context,

    /// Parent coroutine, will always be valid
    parent: *mut Coroutine,

    /// State
    state: State,

    /// Name
    name: Option<String>,
}

unsafe impl Send for Coroutine {}
unsafe impl Sync for Coroutine {}

/// Destroy coroutine and try to reuse std::stack segment.
impl Drop for Coroutine {
    fn drop(&mut self) {
        match self.current_stack_segment.take() {
            Some(stack) => {
                COROUTINE_ENVIRONMENT.with(|env| {
                    let env: &mut Environment = unsafe { transmute(env.get()) };
                    env.stack_pool.give_stack(stack);
                });
            },
            None => {}
        }
    }
}

/// Initialization function for make context
extern "C" fn coroutine_initialize(_: usize, f: *mut ()) -> ! {
    let func: Box<Thunk> = unsafe { transmute(f) };

    let ret = unsafe { try(move|| func.invoke(())) };

    COROUTINE_ENVIRONMENT.with(move|env| {
        let env: &mut Environment = unsafe { transmute(env.get()) };

        match ret {
            Ok(..) => {
                env.running_state = None;
                env.current_running.as_mut().unwrap().0.state = State::Finished;
            }
            Err(err) => {
                env.running_state = Some(err);
                env.current_running.as_mut().unwrap().0.state = State::Panicked;
            }
        }
    });

    loop {
        Coroutine::sched();
    }
}

impl Coroutine {
    pub fn empty() -> Handle {
        Handle(box Coroutine {
            current_stack_segment: None,
            saved_context: Context::empty(),
            parent: ptr::null_mut(),
            state: State::Running,
            name: None,
        })
    }

    pub fn with_name(name: &str) -> Handle {
        Handle(box Coroutine {
            current_stack_segment: None,
            saved_context: Context::empty(),
            parent: ptr::null_mut(),
            state: State::Running,
            name: Some(name.to_string()),
        })
    }

    pub fn spawn_opts<F>(f: F, opts: Options) -> Handle where F: FnOnce() + Send + 'static {
        COROUTINE_ENVIRONMENT.with(move|env| unsafe {
            let env: &mut Environment = transmute(env.get());
            let mut stack = env.stack_pool.take_stack(opts.stack_size);
            let ctx = Context::new(coroutine_initialize,
                                   0,
                                   f,
                                   &mut stack);

            let mut coro: Handle = Coroutine::empty();
            coro.0.saved_context = ctx;
            coro.0.current_stack_segment = Some(stack);
            coro.0.state = State::Suspended;
            coro.0.name = opts.name;
            coro
        })
    }

    /// Spawn a coroutine with default options
    pub fn spawn<F>(f: F) -> Handle where F: FnOnce() + Send + 'static {
        Coroutine::spawn_opts(f, Default::default())
    }

    pub fn sched() {
        COROUTINE_ENVIRONMENT.with(|env| {
            let env: &mut Environment = unsafe { transmute(env.get()) };

            // Move out
            let mut from_coro = env.current_running.as_mut().unwrap();

            match from_coro.state() {
                State::Finished | State::Panicked => {},
                _ => from_coro.0.state = State::Suspended,
            }

            let to_coro: &mut Coroutine = unsafe { transmute_copy(&from_coro.0.parent) };

            Context::swap(&mut from_coro.0.saved_context, &to_coro.saved_context);
        });
    }

    pub fn current() -> HandleGuard {
        HandleGuard
    }

    pub fn state(&self) -> State {
        self.state
    }
}

pub struct HandleGuard;

impl HandleGuard {
    pub fn with<F>(&self, f: F)
        where F: FnOnce(Handle) -> Handle + Send + 'static {

        COROUTINE_ENVIRONMENT.with(|env| {
            let env: &mut Environment = unsafe { transmute(env.get()) };
            env.current_running = Some(f(env.current_running.take().unwrap()));
        });
    }
}

thread_local!(static COROUTINE_ENVIRONMENT: UnsafeCell<Environment> = UnsafeCell::new(Environment::new()));

/// Coroutine managing environment
#[allow(raw_pointer_derive)]
#[derive(Debug)]
struct Environment {
    stack_pool: StackPool,
    current_running: Option<Handle>,
    running_state: Option<Box<Any + Send>>,
}

impl Environment {
    /// Initialize a new environment
    fn new() -> Environment {
        let mut coro = Coroutine::with_name("<Environment Root Coroutine>");
        coro.0.parent = coro.0.deref_mut(); // Pointing to itself

        Environment {
            stack_pool: StackPool::new(),
            current_running: Some(coro),
            running_state: None,
        }
    }
}

#[cfg(test)]
mod test {
    use std::sync::mpsc::channel;

    use test::Bencher;

    use coroutine::Coroutine;

    #[test]
    fn test_coroutine_basic() {
        let (tx, rx) = channel();
        Coroutine::spawn(move|| {
            tx.send(1).unwrap();
        }).resume().unwrap();

        assert_eq!(rx.recv().unwrap(), 1);
    }

    #[test]
    fn test_coroutine_yield() {
        let (tx, rx) = channel();
        let coro = Coroutine::spawn(move|| {
            tx.send(1).unwrap();

            Coroutine::sched();

            tx.send(2).unwrap();
        }).resume().unwrap();
        assert_eq!(rx.recv().unwrap(), 1);
        assert!(rx.try_recv().is_err());

        coro.resume().unwrap();

        assert_eq!(rx.recv().unwrap(), 2);
    }

    #[test]
    fn test_coroutine_spawn_inside() {
        let (tx, rx) = channel();
        Coroutine::spawn(move|| {
            tx.send(1).unwrap();

            Coroutine::spawn(move|| {
                tx.send(2).unwrap();
            }).join().unwrap();

        }).join().unwrap();;

        assert_eq!(rx.recv().unwrap(), 1);
        assert_eq!(rx.recv().unwrap(), 2);
    }

    #[test]
    fn test_coroutine_panic() {
        let coro = Coroutine::spawn(move|| {
            panic!("Panic inside a coroutine!!");
        });
        assert!(coro.join().is_err());
    }

    #[test]
    fn test_coroutine_child_panic() {
        Coroutine::spawn(move|| {
            let _ = Coroutine::spawn(move|| {
                panic!("Panic inside a coroutine's child!!");
            }).join();
        }).join().unwrap();
    }

    #[test]
    fn test_coroutine_resume_after_finished() {
        let mut coro = Coroutine::spawn(move|| {});

        // It is already finished, but we try to resume it
        // Idealy it would come back immediately
        coro = coro.resume().unwrap();

        // Again?
        assert!(coro.resume().is_ok());
    }

    #[test]
    fn test_coroutine_resume_itself() {
        let coro = Coroutine::spawn(move|| {
            // Resume itself
            Coroutine::current().with(|me| {
                me.resume().unwrap()
            });
        });

        assert!(coro.resume().is_ok());
    }

    #[test]
    fn test_coroutine_yield_in_main() {
        Coroutine::sched();
    }

    #[bench]
    fn bench_coroutine_spawning_with_recycle(b: &mut Bencher) {
        b.iter(|| {
            let _ = Coroutine::spawn(move|| {}).resume();
        });
    }

    #[bench]
    fn bench_normal_counting(b: &mut Bencher) {
        b.iter(|| {
            const MAX_NUMBER: usize = 100;

            let (tx, rx) = channel();

            let mut result = 0;
            for _ in 0..MAX_NUMBER {
                tx.send(1).unwrap();
                result += rx.recv().unwrap();
            }
            assert_eq!(result, MAX_NUMBER);
        });
    }

    #[bench]
    fn bench_coroutine_counting(b: &mut Bencher) {
        b.iter(|| {
            const MAX_NUMBER: usize = 100;
            let (tx, rx) = channel();

            let mut coro = Coroutine::spawn(move|| {
                for _ in 0..MAX_NUMBER {
                    tx.send(1).unwrap();
                    Coroutine::sched();
                }
            }).resume().unwrap();;

            let mut result = 0;
            for n in rx.iter() {
                coro = coro.resume().unwrap();
                result += n;
            }
            assert_eq!(result, MAX_NUMBER);
        });
    }
}
<|endoftext|>


<commit_before><commit_msg>Unignore template test. Upstream fix landed.<commit_after><|endoftext|>


<commit_before><commit_msg>Introduce StoreErrorType enum for simple Error type identification<commit_after><|endoftext|>


<commit_before><commit_msg>Add sprite particles example.<commit_after>extern crate lemon3d;
extern crate cgmath;
extern crate rand;

use lemon3d::scene::camera::{Camera, Projection};
use lemon3d::scene::scene2d::Scene2d;
use cgmath as math;
use rand::{Rng, SeedableRng, XorShiftRng};

use lemon3d::graphics::Color;
use lemon3d::scene::{Sprite, Transform, Rect};

#[derive(Debug)]
struct SpriteParticle {
    lifetime: f32,
    velocity: math::Vector3<f32>,
    acceleration: math::Vector3<f32>,
    color: Color,
    size: math::Vector2<f32>,
    handle: lemon3d::ecs::Entity,
}

fn main() {
    let mut scene: Option<Scene2d> = None;
    let mut particles = vec![];
    let mut cal = XorShiftRng::from_seed([0, 1, 2, 3]);

    lemon3d::Application::setup("examples/resources/configs/basic.json")
        .unwrap()
        .perform(|mut app| {
            scene = {
                let mut v = Scene2d::new(&mut app).unwrap();
                let c = Scene2d::camera(&mut v.world_mut());
                v.set_main_camera(c);

                {
                    // Create and bind main camera of scene2d.
                    let dimensions = app.window.dimensions().unwrap();
                    let mut camera = v.world_mut().fetch_mut::<Camera>(c).unwrap();
                    camera.set_aspect(dimensions.0 as f32 / dimensions.1 as f32);
                    camera.set_projection(Projection::Ortho(dimensions.1 as f32 * 0.5));
                }

                for _ in 0..200 {
                    particles.push(None);
                }

                Some(v)
            };
        })
        .run(move |mut app| {
            if let Some(ref mut v) = scene {
                {
                    let mut world = &mut v.world_mut();
                    // Creates sprites randomly.
                    for i in &mut particles {
                        if i.is_none() {
                            let spr = {
                                SpriteParticle {
                                    lifetime: (cal.gen::<u32>() % 5) as f32,
                                    velocity:
                                        math::Vector3::new((cal.gen::<i32>() % 20 - 10) as f32,
                                                           (cal.gen::<i32>() % 20 - 10) as f32,
                                                           0.0),
                                    acceleration:
                                        math::Vector3::new((cal.gen::<i32>() % 10 - 5) as f32,
                                                           (cal.gen::<i32>() % 10 - 5) as f32,
                                                           0.0),
                                    color: [cal.gen::<u8>(), cal.gen::<u8>(), cal.gen::<u8>(), 255]
                                        .into(),
                                    size: math::Vector2::new((cal.gen::<u32>() % 10) as f32 + 5.0,
                                                             (cal.gen::<u32>() % 10) as f32 + 5.0),
                                    handle: Scene2d::sprite(&mut world),
                                }
                            };

                            {
                                let mut sprite = world.fetch_mut::<Sprite>(spr.handle).unwrap();
                                sprite.set_color(&spr.color);

                                let mut rect = world.fetch_mut::<Rect>(spr.handle).unwrap();
                                rect.set_size(&spr.size);
                            }

                            *i = Some(spr);
                            break;
                        }
                    }
                }

                let mut removes = vec![];

                {
                    let dt = app.engine.timestep_in_seconds();
                    let world = &mut v.world_mut();
                    let (_, mut arenas) = world.view_with_2::<Transform, Sprite>();
                    for (i, w) in particles.iter_mut().enumerate() {
                        if let Some(ref mut particle) = *w {
                            particle.velocity += particle.acceleration * dt;
                            arenas.0.get_mut(particle.handle).unwrap().translate(particle.velocity);

                            particle.lifetime -= dt;
                            if particle.lifetime < 0.0 {
                                removes.push(i);
                            }
                        }
                    }
                }

                {
                    let mut world = &mut v.world_mut();
                    for i in removes {
                        if let Some(ref v) = particles[i] {
                            world.free(v.handle);
                        }
                        particles[i] = None;
                    }
                }

                v.run_one_frame(&mut app).unwrap();
            }
            return true;
        });
}<|endoftext|>


<commit_before><commit_msg>Update tests<commit_after><|endoftext|>


<commit_before><commit_msg>desync mob movements<commit_after><|endoftext|>