<commit_before>use std::sync::{Arc, RwLock};
use std::option::Option;
use std::collections::{HashMap, HashSet};

use rocksdb::DB;
use mio::{self, EventLoop, EventLoopConfig};
use protobuf;
use uuid::Uuid;

use proto::raft_serverpb::{RaftMessage, StoreIdent};
use proto::raft_cmdpb::{self as cmd, RaftCommandRequest, RaftCommandResponse};
use raftserver::{Result, other};
use proto::metapb;
use super::{SendCh, Msg};
use super::keys;
use super::engine::Retriever;
use super::config::Config;
use super::peer::{Peer, PendingCmd};
use super::msg::Callback;
use super::cmd_resp::{self, bind_uuid};
use super::transport::Transport;

pub struct Store<T: Transport> {
    cfg: Config,
    ident: StoreIdent,
    engine: Arc<DB>,
    sender: SendCh,
    event_loop: Option<EventLoop<Store<T>>>,

    peers: HashMap<u64, Peer>,
    pending_raft_groups: HashSet<u64>,

    trans: Arc<RwLock<T>>,
}

impl<T: Transport> Store<T> {
    pub fn new(cfg: Config, engine: Arc<DB>, trans: Arc<RwLock<T>>) -> Result<Store<T>> {
        let ident: StoreIdent = try!(load_store_ident(engine.as_ref()).and_then(|res| {
            match res {
                None => Err(other("store must be bootstrapped first")),
                Some(ident) => Ok(ident),
            }
        }));

        // We use base raft tick as the event loop timer tick.
        let mut event_cfg = EventLoopConfig::new();
        event_cfg.timer_tick_ms(cfg.raft_base_tick_interval);
        let event_loop = try!(EventLoop::configured(event_cfg));

        let sender = SendCh::new(event_loop.channel());

        Ok(Store {
            cfg: cfg,
            ident: ident,
            engine: engine,
            sender: sender,
            event_loop: Some(event_loop),
            peers: HashMap::new(),
            pending_raft_groups: HashSet::new(),
            trans: trans,
        })
    }

    // Do something before store runs.
    fn prepare(&mut self) -> Result<()> {
        // Scan region meta to get saved regions.
        let start_key = keys::REGION_META_MIN_KEY;
        let end_key = keys::REGION_META_MAX_KEY;
        let engine = self.engine.clone();
        try!(engine.scan(start_key,
                         end_key,
                         &mut |key, value| -> Result<bool> {
                             let (_, suffix) = try!(keys::decode_region_meta_key(key));
                             if suffix != keys::REGION_INFO_SUFFIX {
                                 return Ok(true);
                             }

                             let region = try!(protobuf::parse_from_bytes::<metapb::Region>(value));
                             let region_id = region.get_region_id();
                             let peer = try!(Peer::create(self, region));
                             // TODO: check duplicated region id later?
                             self.peers.insert(region_id, peer);
                             Ok(true)
                         }));

        Ok(())
    }

    pub fn run(&mut self) -> Result<()> {
        try!(self.prepare());

        let mut event_loop = self.event_loop.take().unwrap();
        self.register_raft_base_tick(&mut event_loop);
        try!(event_loop.run(self));
        Ok(())
    }

    pub fn get_sendch(&self) -> SendCh {
        self.sender.clone()
    }

    pub fn get_engine(&self) -> Arc<DB> {
        self.engine.clone()
    }

    pub fn get_ident(&self) -> &StoreIdent {
        &self.ident
    }

    pub fn get_store_id(&self) -> u64 {
        self.ident.get_store_id()
    }

    pub fn get_config(&self) -> &Config {
        &self.cfg
    }

    fn register_raft_base_tick(&self, event_loop: &mut EventLoop<Self>) {
        // If we register raft base tick failed, the whole raft can't run correctly,
        // TODO: shutdown the store?
        if let Err(e) = register_timer(event_loop,
                                       Msg::RaftBaseTick,
                                       self.cfg.raft_base_tick_interval) {
            error!("register raft base tick err: {:?}", e);
        };
    }

    fn handle_raft_base_tick(&mut self, event_loop: &mut EventLoop<Self>) {
        for (region_id, peer) in &mut self.peers {
            peer.raft_group.tick();
            self.pending_raft_groups.insert(*region_id);
        }

        self.register_raft_base_tick(event_loop);
    }

    // Clippy doesn't allow hash_map contains_key followed by insert, and suggests
    // using entry().or_insert() instead, but we can't use this because creating peer
    // may fail, so we allow map_entry.
    #[allow(map_entry)]
    fn handle_raft_message(&mut self, msg: RaftMessage) -> Result<()> {
        let region_id = msg.get_region_id();
        let from_peer = msg.get_from_peer();
        let to_peer = msg.get_to_peer();
        debug!("handle raft message for region {}, from {} to {}",
               region_id,
               from_peer.get_peer_id(),
               to_peer.get_peer_id());

        {
            let mut trans = self.trans.write().unwrap();
            trans.cache_peer(from_peer.get_peer_id(), from_peer.clone());
            trans.cache_peer(to_peer.get_peer_id(), to_peer.clone());
        }

        if !self.peers.contains_key(&region_id) {
            let peer = try!(Peer::replicate(self, region_id, to_peer.get_peer_id()));
            self.peers.insert(region_id, peer);
        }

        let mut peer = self.peers.get_mut(&region_id).unwrap();

        try!(peer.raft_group.step(msg.get_message().clone()));

        // Add in pending raft group for later handing ready.
        self.pending_raft_groups.insert(region_id);

        Ok(())
    }

    fn handle_raft_ready(&mut self) -> Result<()> {
        let ids = self.pending_raft_groups.drain();

        for region_id in ids {
            if let Some(peer) = self.peers.get_mut(&region_id) {
                if let Err(e) = peer.handle_raft_ready(&self.trans) {
                    // TODO: should we panic here or shutdown the store?
                    error!("handle raft ready err: {:?}", e);
                    return Err(e);
                }
            }
        }

        Ok(())
    }

    fn propose_raft_command(&mut self, msg: RaftCommandRequest, cb: Callback) -> Result<()> {
        let mut resp: RaftCommandResponse;
        let uuid: Uuid = match Uuid::from_bytes(msg.get_header().get_uuid()) {
            None => {
                resp = cmd_resp::message_error("missing request uuid");
                return cb.call_box((resp,));
            }
            Some(uuid) => uuid,
        };

        if msg.has_status_request() {
            // For status commands, we handle it here directly.
            resp = match self.execute_status_command(msg) {
                Err(e) => cmd_resp::message_error(format!("{:?}", e)),
                Ok(resp) => resp,
            };
            bind_uuid(&mut resp, uuid);
            return cb.call_box((resp,));
        }

        let region_id = msg.get_header().get_region_id();
        let mut peer = match self.peers.get_mut(&region_id) {
            None => {
                resp = cmd_resp::region_not_found_error(region_id);
                bind_uuid(&mut resp, uuid);
                return cb.call_box((resp,));
            }
            Some(peer) => peer,
        };

        if !peer.is_leader() {
            let trans = self.trans.read().unwrap();
            resp = cmd_resp::not_leader_error(region_id, trans.get_peer(peer.get_leader()));
            bind_uuid(&mut resp, uuid);
            return cb.call_box((resp,));
        }

        let peer_id = msg.get_header().get_peer().get_peer_id();
        if peer.get_peer_id() != peer_id {
            resp = cmd_resp::message_error(format!("mismatch peer id {} != {}",
                                                   peer.get_peer_id(),
                                                   peer_id));
            bind_uuid(&mut resp, uuid);
            return cb.call_box((resp,));
        }

        if peer.pending_cmds.contains_key(&uuid) {
            resp = cmd_resp::message_error(format!("duplicated uuid {:?}", uuid));
            bind_uuid(&mut resp, uuid);
            return cb.call_box((resp,));
        }

        // Notice:
        // Here means the peer is leader, it can still step down to follower later,
        // but it doesn't matter, if the peer is not leader, the proposing command
        // log entry can't be committed.

        // TODO: support handing read-only commands later.
        // for read-only, if we don't care stale read, we can
        // execute these commands immediately in leader.

        let mut pending_cmd = PendingCmd {
            uuid: uuid,
            cb: None,
            cmd: Some(msg),
        };

        match peer.propose_pending_cmd(&mut pending_cmd) {
            Err(e) => {
                resp = cmd_resp::message_error(format!("{:?}", e));
                bind_uuid(&mut resp, uuid);
                return cb.call_box((resp,));
            }
            Ok(()) => (), // nothing to do.
        };

        // Keep the callback in pending_cmd so that we can call it later
        // after command applied.
        pending_cmd.cb = Some(cb);
        peer.pending_cmds.insert(uuid, pending_cmd);

        self.pending_raft_groups.insert(region_id);

        // TODO: add timeout, if the command is not applied after timeout,
        // we will call the callback with timeout error.

        Ok(())
    }
}

fn load_store_ident<T: Retriever>(r: &T) -> Result<Option<StoreIdent>> {
    let ident = try!(r.get_msg::<StoreIdent>(&keys::store_ident_key()));

    Ok(ident)
}

fn register_timer<T: Transport>(event_loop: &mut EventLoop<Store<T>>,
                                msg: Msg,
                                delay: u64)
                                -> Result<mio::Timeout> {
    // TODO: now mio TimerError doesn't implement Error trait,
    // so we can't use `try!` directly.
    event_loop.timeout_ms(msg, delay).map_err(|e| other(format!("register timer err: {:?}", e)))
}

impl<T: Transport> mio::Handler for Store<T> {
    type Timeout = Msg;
    type Message = Msg;

    fn notify(&mut self, event_loop: &mut EventLoop<Self>, msg: Msg) {
        match msg {
            Msg::RaftMessage(data) => {
                if let Err(e) = self.handle_raft_message(data) {
                    error!("handle raft message err: {:?}", e);
                }
            }
            Msg::RaftCommand{request, callback} => {
                if let Err(e) = self.propose_raft_command(request, callback) {
                    error!("propose raft command err: {:?}", e);
                }
            }
            Msg::Quit => {
                info!("receive quit message");
                event_loop.shutdown();
            }
            _ => panic!("invalid notify msg type {:?}", msg),
        }
    }

    fn timeout(&mut self, event_loop: &mut EventLoop<Self>, timeout: Msg) {
        match timeout {
            Msg::RaftBaseTick => self.handle_raft_base_tick(event_loop),
            _ => panic!("invalid timeout msg type {:?}", timeout),
        }
    }

    fn tick(&mut self, event_loop: &mut EventLoop<Self>) {
        if !event_loop.is_running() {
            // TODO: do some close here.
            return;
        }

        // We handle raft ready in event loop.
        if let Err(e) = self.handle_raft_ready() {
            // TODO: should we panic here or shutdown the store?
            error!("handle raft ready err: {:?}", e);
        }
    }
}

impl<T: Transport> Store<T> {
    // Handle status commands here, separate the logic, maybe we can move it
    // to another file later.
    // Unlike other commands (write or admin), status commands only show current
    // store status, so no need to handle it in raft group.
    fn execute_status_command(&mut self,
                              request: RaftCommandRequest)
                              -> Result<RaftCommandResponse> {
        let cmd_type = request.get_status_request().get_cmd_type();
        let mut response = try!(match cmd_type {
            cmd::StatusCommandType::RegionLeader => self.execute_region_leader(request),
            e => Err(other(format!("unsupported status command type {:?}", e))),
        });
        response.set_cmd_type(cmd_type);

        let mut resp = RaftCommandResponse::new();
        resp.set_status_response(response);
        Ok(resp)
    }

    fn execute_region_leader(&mut self,
                             request: RaftCommandRequest)
                             -> Result<cmd::StatusResponse> {
        let region_id = request.get_header().get_region_id();
        let peer = match self.peers.get_mut(&region_id) {
            None => return Err(other(format!("region {} not found", region_id))),
            Some(peer) => peer,
        };

        let mut resp = cmd::StatusResponse::new();
        let trans = self.trans.read().unwrap();
        if let Some(leader) = trans.get_peer(peer.get_leader()) {
            resp.mut_region_leader().set_leader(leader);
        }

        Ok(resp)
    }
}
<commit_msg>*: Rename sender to sendch<commit_after>use std::sync::{Arc, RwLock};
use std::option::Option;
use std::collections::{HashMap, HashSet};

use rocksdb::DB;
use mio::{self, EventLoop, EventLoopConfig};
use protobuf;
use uuid::Uuid;

use proto::raft_serverpb::{RaftMessage, StoreIdent};
use proto::raft_cmdpb::{self as cmd, RaftCommandRequest, RaftCommandResponse};
use raftserver::{Result, other};
use proto::metapb;
use super::{SendCh, Msg};
use super::keys;
use super::engine::Retriever;
use super::config::Config;
use super::peer::{Peer, PendingCmd};
use super::msg::Callback;
use super::cmd_resp::{self, bind_uuid};
use super::transport::Transport;

pub struct Store<T: Transport> {
    cfg: Config,
    ident: StoreIdent,
    engine: Arc<DB>,
    sendch: SendCh,
    event_loop: Option<EventLoop<Store<T>>>,

    peers: HashMap<u64, Peer>,
    pending_raft_groups: HashSet<u64>,

    trans: Arc<RwLock<T>>,
}

impl<T: Transport> Store<T> {
    pub fn new(cfg: Config, engine: Arc<DB>, trans: Arc<RwLock<T>>) -> Result<Store<T>> {
        let ident: StoreIdent = try!(load_store_ident(engine.as_ref()).and_then(|res| {
            match res {
                None => Err(other("store must be bootstrapped first")),
                Some(ident) => Ok(ident),
            }
        }));

        // We use base raft tick as the event loop timer tick.
        let mut event_cfg = EventLoopConfig::new();
        event_cfg.timer_tick_ms(cfg.raft_base_tick_interval);
        let event_loop = try!(EventLoop::configured(event_cfg));

        let sendch = SendCh::new(event_loop.channel());

        Ok(Store {
            cfg: cfg,
            ident: ident,
            engine: engine,
            sendch: sendch,
            event_loop: Some(event_loop),
            peers: HashMap::new(),
            pending_raft_groups: HashSet::new(),
            trans: trans,
        })
    }

    // Do something before store runs.
    fn prepare(&mut self) -> Result<()> {
        // Scan region meta to get saved regions.
        let start_key = keys::REGION_META_MIN_KEY;
        let end_key = keys::REGION_META_MAX_KEY;
        let engine = self.engine.clone();
        try!(engine.scan(start_key,
                         end_key,
                         &mut |key, value| -> Result<bool> {
                             let (_, suffix) = try!(keys::decode_region_meta_key(key));
                             if suffix != keys::REGION_INFO_SUFFIX {
                                 return Ok(true);
                             }

                             let region = try!(protobuf::parse_from_bytes::<metapb::Region>(value));
                             let region_id = region.get_region_id();
                             let peer = try!(Peer::create(self, region));
                             // TODO: check duplicated region id later?
                             self.peers.insert(region_id, peer);
                             Ok(true)
                         }));

        Ok(())
    }

    pub fn run(&mut self) -> Result<()> {
        try!(self.prepare());

        let mut event_loop = self.event_loop.take().unwrap();
        self.register_raft_base_tick(&mut event_loop);
        try!(event_loop.run(self));
        Ok(())
    }

    pub fn get_sendch(&self) -> SendCh {
        self.sendch.clone()
    }

    pub fn get_engine(&self) -> Arc<DB> {
        self.engine.clone()
    }

    pub fn get_ident(&self) -> &StoreIdent {
        &self.ident
    }

    pub fn get_store_id(&self) -> u64 {
        self.ident.get_store_id()
    }

    pub fn get_config(&self) -> &Config {
        &self.cfg
    }

    fn register_raft_base_tick(&self, event_loop: &mut EventLoop<Self>) {
        // If we register raft base tick failed, the whole raft can't run correctly,
        // TODO: shutdown the store?
        if let Err(e) = register_timer(event_loop,
                                       Msg::RaftBaseTick,
                                       self.cfg.raft_base_tick_interval) {
            error!("register raft base tick err: {:?}", e);
        };
    }

    fn handle_raft_base_tick(&mut self, event_loop: &mut EventLoop<Self>) {
        for (region_id, peer) in &mut self.peers {
            peer.raft_group.tick();
            self.pending_raft_groups.insert(*region_id);
        }

        self.register_raft_base_tick(event_loop);
    }

    // Clippy doesn't allow hash_map contains_key followed by insert, and suggests
    // using entry().or_insert() instead, but we can't use this because creating peer
    // may fail, so we allow map_entry.
    #[allow(map_entry)]
    fn handle_raft_message(&mut self, msg: RaftMessage) -> Result<()> {
        let region_id = msg.get_region_id();
        let from_peer = msg.get_from_peer();
        let to_peer = msg.get_to_peer();
        debug!("handle raft message for region {}, from {} to {}",
               region_id,
               from_peer.get_peer_id(),
               to_peer.get_peer_id());

        {
            let mut trans = self.trans.write().unwrap();
            trans.cache_peer(from_peer.get_peer_id(), from_peer.clone());
            trans.cache_peer(to_peer.get_peer_id(), to_peer.clone());
        }

        if !self.peers.contains_key(&region_id) {
            let peer = try!(Peer::replicate(self, region_id, to_peer.get_peer_id()));
            self.peers.insert(region_id, peer);
        }

        let mut peer = self.peers.get_mut(&region_id).unwrap();

        try!(peer.raft_group.step(msg.get_message().clone()));

        // Add in pending raft group for later handing ready.
        self.pending_raft_groups.insert(region_id);

        Ok(())
    }

    fn handle_raft_ready(&mut self) -> Result<()> {
        let ids = self.pending_raft_groups.drain();

        for region_id in ids {
            if let Some(peer) = self.peers.get_mut(&region_id) {
                if let Err(e) = peer.handle_raft_ready(&self.trans) {
                    // TODO: should we panic here or shutdown the store?
                    error!("handle raft ready err: {:?}", e);
                    return Err(e);
                }
            }
        }

        Ok(())
    }

    fn propose_raft_command(&mut self, msg: RaftCommandRequest, cb: Callback) -> Result<()> {
        let mut resp: RaftCommandResponse;
        let uuid: Uuid = match Uuid::from_bytes(msg.get_header().get_uuid()) {
            None => {
                resp = cmd_resp::message_error("missing request uuid");
                return cb.call_box((resp,));
            }
            Some(uuid) => uuid,
        };

        if msg.has_status_request() {
            // For status commands, we handle it here directly.
            resp = match self.execute_status_command(msg) {
                Err(e) => cmd_resp::message_error(format!("{:?}", e)),
                Ok(resp) => resp,
            };
            bind_uuid(&mut resp, uuid);
            return cb.call_box((resp,));
        }

        let region_id = msg.get_header().get_region_id();
        let mut peer = match self.peers.get_mut(&region_id) {
            None => {
                resp = cmd_resp::region_not_found_error(region_id);
                bind_uuid(&mut resp, uuid);
                return cb.call_box((resp,));
            }
            Some(peer) => peer,
        };

        if !peer.is_leader() {
            let trans = self.trans.read().unwrap();
            resp = cmd_resp::not_leader_error(region_id, trans.get_peer(peer.get_leader()));
            bind_uuid(&mut resp, uuid);
            return cb.call_box((resp,));
        }

        let peer_id = msg.get_header().get_peer().get_peer_id();
        if peer.get_peer_id() != peer_id {
            resp = cmd_resp::message_error(format!("mismatch peer id {} != {}",
                                                   peer.get_peer_id(),
                                                   peer_id));
            bind_uuid(&mut resp, uuid);
            return cb.call_box((resp,));
        }

        if peer.pending_cmds.contains_key(&uuid) {
            resp = cmd_resp::message_error(format!("duplicated uuid {:?}", uuid));
            bind_uuid(&mut resp, uuid);
            return cb.call_box((resp,));
        }

        // Notice:
        // Here means the peer is leader, it can still step down to follower later,
        // but it doesn't matter, if the peer is not leader, the proposing command
        // log entry can't be committed.

        // TODO: support handing read-only commands later.
        // for read-only, if we don't care stale read, we can
        // execute these commands immediately in leader.

        let mut pending_cmd = PendingCmd {
            uuid: uuid,
            cb: None,
            cmd: Some(msg),
        };

        match peer.propose_pending_cmd(&mut pending_cmd) {
            Err(e) => {
                resp = cmd_resp::message_error(format!("{:?}", e));
                bind_uuid(&mut resp, uuid);
                return cb.call_box((resp,));
            }
            Ok(()) => (), // nothing to do.
        };

        // Keep the callback in pending_cmd so that we can call it later
        // after command applied.
        pending_cmd.cb = Some(cb);
        peer.pending_cmds.insert(uuid, pending_cmd);

        self.pending_raft_groups.insert(region_id);

        // TODO: add timeout, if the command is not applied after timeout,
        // we will call the callback with timeout error.

        Ok(())
    }
}

fn load_store_ident<T: Retriever>(r: &T) -> Result<Option<StoreIdent>> {
    let ident = try!(r.get_msg::<StoreIdent>(&keys::store_ident_key()));

    Ok(ident)
}

fn register_timer<T: Transport>(event_loop: &mut EventLoop<Store<T>>,
                                msg: Msg,
                                delay: u64)
                                -> Result<mio::Timeout> {
    // TODO: now mio TimerError doesn't implement Error trait,
    // so we can't use `try!` directly.
    event_loop.timeout_ms(msg, delay).map_err(|e| other(format!("register timer err: {:?}", e)))
}

impl<T: Transport> mio::Handler for Store<T> {
    type Timeout = Msg;
    type Message = Msg;

    fn notify(&mut self, event_loop: &mut EventLoop<Self>, msg: Msg) {
        match msg {
            Msg::RaftMessage(data) => {
                if let Err(e) = self.handle_raft_message(data) {
                    error!("handle raft message err: {:?}", e);
                }
            }
            Msg::RaftCommand{request, callback} => {
                if let Err(e) = self.propose_raft_command(request, callback) {
                    error!("propose raft command err: {:?}", e);
                }
            }
            Msg::Quit => {
                info!("receive quit message");
                event_loop.shutdown();
            }
            _ => panic!("invalid notify msg type {:?}", msg),
        }
    }

    fn timeout(&mut self, event_loop: &mut EventLoop<Self>, timeout: Msg) {
        match timeout {
            Msg::RaftBaseTick => self.handle_raft_base_tick(event_loop),
            _ => panic!("invalid timeout msg type {:?}", timeout),
        }
    }

    fn tick(&mut self, event_loop: &mut EventLoop<Self>) {
        if !event_loop.is_running() {
            // TODO: do some close here.
            return;
        }

        // We handle raft ready in event loop.
        if let Err(e) = self.handle_raft_ready() {
            // TODO: should we panic here or shutdown the store?
            error!("handle raft ready err: {:?}", e);
        }
    }
}

impl<T: Transport> Store<T> {
    // Handle status commands here, separate the logic, maybe we can move it
    // to another file later.
    // Unlike other commands (write or admin), status commands only show current
    // store status, so no need to handle it in raft group.
    fn execute_status_command(&mut self,
                              request: RaftCommandRequest)
                              -> Result<RaftCommandResponse> {
        let cmd_type = request.get_status_request().get_cmd_type();
        let mut response = try!(match cmd_type {
            cmd::StatusCommandType::RegionLeader => self.execute_region_leader(request),
            e => Err(other(format!("unsupported status command type {:?}", e))),
        });
        response.set_cmd_type(cmd_type);

        let mut resp = RaftCommandResponse::new();
        resp.set_status_response(response);
        Ok(resp)
    }

    fn execute_region_leader(&mut self,
                             request: RaftCommandRequest)
                             -> Result<cmd::StatusResponse> {
        let region_id = request.get_header().get_region_id();
        let peer = match self.peers.get_mut(&region_id) {
            None => return Err(other(format!("region {} not found", region_id))),
            Some(peer) => peer,
        };

        let mut resp = cmd::StatusResponse::new();
        let trans = self.trans.read().unwrap();
        if let Some(leader) = trans.get_peer(peer.get_leader()) {
            resp.mut_region_leader().set_leader(leader);
        }

        Ok(resp)
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]
#![crate_type="staticlib"]
#![no_std]

//! Sample application for BlueNRG communication over SPI in X-NUCLEO-IDB04A1
//! extension board for NUCLEO-L152RE

#[phase(plugin, link)]
extern crate core;
extern crate zinc;

use core::intrinsics::abort;
// "curious module hack" - a workaround for `fmt` module being looked in `std`
// by the `write!` macro
mod std {
  pub use core::fmt;
}

//TODO(kvark): temporary `u8 -> str` conversion until #235 is resolved
fn map_byte(s: u8) -> (&'static str, &'static str) {
  fn map_hex(h: u8) -> &'static str {
      match h {
        0x0 => "0",
        0x1 => "1",
        0x2 => "2",
        0x3 => "3",
        0x4 => "4",
        0x5 => "5",
        0x6 => "6",
        0x7 => "7",
        0x8 => "8",
        0x9 => "9",
        0xA => "A",
        0xB => "B",
        0xC => "C",
        0xD => "D",
        0xE => "E",
        0xF => "F",
        _ => "",
      }
  }
  (map_hex(s>>4), map_hex(s&0xF))
}

#[no_mangle]
pub unsafe fn main() {
  use core::fmt::FormatWriter;
  use core::result;
  use zinc::drivers::bluenrg;
  use zinc::hal;
  use zinc::hal::pin::Gpio;
  use zinc::hal::stm32l1::{init, pin, spi, usart};

  zinc::hal::mem_init::init_stack();
  zinc::hal::mem_init::init_data();

  let sys_clock = init::ClockConfig::new_default();
  sys_clock.setup();

  let _usart_tx = pin::Pin::new(pin::Port::PortA, 2,
    pin::Mode::AltFunction(
      pin::AltMode::AfUsart1_Usart2_Usart3,
      pin::OutputType::OutPushPull,
      pin::Speed::VeryLow),
    pin::PullType::PullNone);

  let mut uart = usart::Usart::new(usart::UsartPeripheral::Usart2, 38400, usart::WordLen::WordLen8bits,
    hal::uart::Parity::Disabled, usart::StopBit::StopBit1bit, &sys_clock);
  let _ = write!(&mut uart, "BlueNRG test app for STM32L1\n");

  let _spi_clock = pin::Pin::new(pin::Port::PortB, 3,
    pin::Mode::AltFunction(pin::AltMode::AfSpi1_Spi2, pin::OutputType::OutPushPull, pin::Speed::Medium),
    pin::PullType::PullDown);

  let _spi_in = pin::Pin::new(pin::Port::PortA, 6,
    pin::Mode::AltFunction(pin::AltMode::AfSpi1_Spi2, pin::OutputType::OutPushPull, pin::Speed::Medium),
    pin::PullType::PullNone);

  let _spi_out = pin::Pin::new(pin::Port::PortA, 7,
    pin::Mode::AltFunction(pin::AltMode::AfSpi1_Spi2, pin::OutputType::OutPushPull, pin::Speed::Medium),
    pin::PullType::PullNone);

  let spi_csn = pin::Pin::new(pin::Port::PortA, 1,
    pin::Mode::GpioOut(pin::OutputType::OutPushPull, pin::Speed::Medium),
    pin::PullType::PullUp);
  spi_csn.set_high();

  let spi = spi::Spi::new(spi::Peripheral::Spi1, spi::Direction::FullDuplex,
    spi::Role::Master, spi::DataSize::U8, spi::DataFormat::MsbFirst, 1).
    unwrap_or_else(|_| {
      let _ = write!(&mut uart, "SPI failed to initialize");
      abort()
    });

  let bnrg_reset = pin::Pin::new(pin::Port::PortA, 8,
    pin::Mode::GpioOut(pin::OutputType::OutPushPull, pin::Speed::VeryLow),
    pin::PullType::PullUp);

  bnrg_reset.set_low();
  let _ = write!(&mut uart, "SPI created, status = {}\n",
    map_byte(spi.get_status()));
  bnrg_reset.set_high();

  let blue = bluenrg::BlueNrg::new(spi_csn, spi);

  let _ = match blue.wakeup(100) {
    result::Ok((size_write, size_read)) => write!(&mut uart,
      "BlueNRG is ready, write size = {}, read size = {}\n",
      map_byte(size_write as u8), map_byte(size_read as u8)),
    result::Err(bluenrg::Error::Sleeping) => write!(&mut uart,
      "BlueNRG is sleeping\n"),
    result::Err(bluenrg::Error::Allocating) => write!(&mut uart,
      "BlueNRG is allocating buffers\n"),
    result::Err(bluenrg::Error::Unknown(status)) => write!(&mut uart,
      "BlueNRG unknown status = {}\n", map_byte(status)),
    result::Err(bluenrg::Error::BufferSize(_)) => write!(&mut uart, ""),
  };

  loop {}
}
<commit_msg>app_bluenrg: Fix enum namespace for Result<commit_after>#![feature(phase)]
#![crate_type="staticlib"]
#![no_std]

//! Sample application for BlueNRG communication over SPI in X-NUCLEO-IDB04A1
//! extension board for NUCLEO-L152RE

#[phase(plugin, link)]
extern crate core;
extern crate zinc;

use core::intrinsics::abort;
// "curious module hack" - a workaround for `fmt` module being looked in `std`
// by the `write!` macro
mod std {
  pub use core::fmt;
}

//TODO(kvark): temporary `u8 -> str` conversion until #235 is resolved
fn map_byte(s: u8) -> (&'static str, &'static str) {
  fn map_hex(h: u8) -> &'static str {
      match h {
        0x0 => "0",
        0x1 => "1",
        0x2 => "2",
        0x3 => "3",
        0x4 => "4",
        0x5 => "5",
        0x6 => "6",
        0x7 => "7",
        0x8 => "8",
        0x9 => "9",
        0xA => "A",
        0xB => "B",
        0xC => "C",
        0xD => "D",
        0xE => "E",
        0xF => "F",
        _ => "",
      }
  }
  (map_hex(s>>4), map_hex(s&0xF))
}

#[no_mangle]
pub unsafe fn main() {
  use core::fmt::FormatWriter;
  use core::result::Result;
  use zinc::drivers::bluenrg;
  use zinc::hal;
  use zinc::hal::pin::Gpio;
  use zinc::hal::stm32l1::{init, pin, spi, usart};

  zinc::hal::mem_init::init_stack();
  zinc::hal::mem_init::init_data();

  let sys_clock = init::ClockConfig::new_default();
  sys_clock.setup();

  let _usart_tx = pin::Pin::new(pin::Port::PortA, 2,
    pin::Mode::AltFunction(
      pin::AltMode::AfUsart1_Usart2_Usart3,
      pin::OutputType::OutPushPull,
      pin::Speed::VeryLow),
    pin::PullType::PullNone);

  let mut uart = usart::Usart::new(usart::UsartPeripheral::Usart2, 38400, usart::WordLen::WordLen8bits,
    hal::uart::Parity::Disabled, usart::StopBit::StopBit1bit, &sys_clock);
  let _ = write!(&mut uart, "BlueNRG test app for STM32L1\n");

  let _spi_clock = pin::Pin::new(pin::Port::PortB, 3,
    pin::Mode::AltFunction(pin::AltMode::AfSpi1_Spi2, pin::OutputType::OutPushPull, pin::Speed::Medium),
    pin::PullType::PullDown);

  let _spi_in = pin::Pin::new(pin::Port::PortA, 6,
    pin::Mode::AltFunction(pin::AltMode::AfSpi1_Spi2, pin::OutputType::OutPushPull, pin::Speed::Medium),
    pin::PullType::PullNone);

  let _spi_out = pin::Pin::new(pin::Port::PortA, 7,
    pin::Mode::AltFunction(pin::AltMode::AfSpi1_Spi2, pin::OutputType::OutPushPull, pin::Speed::Medium),
    pin::PullType::PullNone);

  let spi_csn = pin::Pin::new(pin::Port::PortA, 1,
    pin::Mode::GpioOut(pin::OutputType::OutPushPull, pin::Speed::Medium),
    pin::PullType::PullUp);
  spi_csn.set_high();

  let spi = spi::Spi::new(spi::Peripheral::Spi1, spi::Direction::FullDuplex,
    spi::Role::Master, spi::DataSize::U8, spi::DataFormat::MsbFirst, 1).
    unwrap_or_else(|_| {
      let _ = write!(&mut uart, "SPI failed to initialize");
      abort()
    });

  let bnrg_reset = pin::Pin::new(pin::Port::PortA, 8,
    pin::Mode::GpioOut(pin::OutputType::OutPushPull, pin::Speed::VeryLow),
    pin::PullType::PullUp);

  bnrg_reset.set_low();
  let _ = write!(&mut uart, "SPI created, status = {}\n",
    map_byte(spi.get_status()));
  bnrg_reset.set_high();

  let blue = bluenrg::BlueNrg::new(spi_csn, spi);

  let _ = match blue.wakeup(100) {
    Result::Ok((size_write, size_read)) => write!(&mut uart,
      "BlueNRG is ready, write size = {}, read size = {}\n",
      map_byte(size_write as u8), map_byte(size_read as u8)),
    Result::Err(bluenrg::Error::Sleeping) => write!(&mut uart,
      "BlueNRG is sleeping\n"),
    Result::Err(bluenrg::Error::Allocating) => write!(&mut uart,
      "BlueNRG is allocating buffers\n"),
    Result::Err(bluenrg::Error::Unknown(status)) => write!(&mut uart,
      "BlueNRG unknown status = {}\n", map_byte(status)),
    Result::Err(bluenrg::Error::BufferSize(_)) => write!(&mut uart, ""),
  };

  loop {}
}
<|endoftext|>


<commit_before>#[crate_id(name="mkdir", vers="1.0.0", author="Nicholas Juszczak")];

/**
 * This file is part of the uutils coreutils package.
 *
 * (c) Nicholas Juszczak <juszczakn@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern mod extra;

use std::os;
use std::io::{fs, stderr};
use std::num::strconv;
use extra::getopts::groups;

static VERSION: &'static str = "1.0.0";

/**
 * Handles option parsing
 */
fn main() {
    let args = os::args();

    let opts = ~[
        // Linux-specific options, not implemented
        // groups::optflag("Z", "context", "set SELinux secutiry context" +
        // " of each created directory to CTX"),
        groups::optopt("m", "mode", "set file mode", "755"),
        groups::optflag("p", "parents", "make parent directories as needed"),
        groups::optflag("v", "verbose",
                        "print a message for each printed directory"),
        groups::optflag("h", "help", "display this help"),
        groups::optflag("", "version", "display this version")
    ];

    let matches = match groups::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut stderr() as &mut Writer,
                     "Invalid options\n{}", f.to_err_msg());
            os::set_exit_status(1);
            return;
        }
    };

    if args.len() == 1 || matches.opt_present("help") {
        print_help(opts);
        return;
    }
    if matches.opt_present("version") {
        println!("mkdir v{}", VERSION);
        return;
    }
    let verbose_flag = matches.opt_present("verbose");
    let mk_parents = matches.opt_present("parents");

    // Translate a ~str in octal form to u32, default to 755
    // Not tested on Windows
    let mode_match = matches.opts_str(&[~"mode"]);
    let mode: u32 = if mode_match.is_some() {
        let m = mode_match.unwrap();
        let res = strconv::from_str_common(m, 8, false, false, false,
                                           strconv::ExpNone,
                                           false, false);
        if res.is_some() {
            res.unwrap()
        } else {
            writeln!(&mut stderr() as &mut Writer,
                     "Error: no mode given");
            os::set_exit_status(1);
            return;
        }
    } else {
        0o755
    };

    let dirs = matches.free;
    exec(dirs, mk_parents, mode, verbose_flag);
}

fn print_help(opts: &[groups::OptGroup]) {
    println!("mkdir v{} - make a new directory with the given path", VERSION);
    println!("");
    println!("Usage:");
    print!("{}", groups::usage("Create the given DIRECTORY(ies)" +
                               " if they do not exist", opts));
}

/**
 * Create the list of new directories
 */
fn exec(dirs: ~[~str], mk_parents: bool, mode: u32, verbose: bool) {
    let mut parent_dirs: ~[~str] = ~[];
    if mk_parents {
        for dir in dirs.iter() {
            let path = Path::new((*dir).clone());
            // Build list of parent dirs which need to be created
            let parent = path.dirname_str();
            match parent {
                Some(p) => {
                    if !Path::new(p).exists() {
                        parent_dirs.push(p.into_owned())
                    }
                },
                None => ()
            }
        }
    }
    // Recursively build parent dirs that are needed
    if !parent_dirs.is_empty() {
        exec(parent_dirs, mk_parents, mode, verbose);
    }

    for dir in dirs.iter() {
        let path = Path::new((*dir).clone());
        // Determine if parent directory to the one to
        // be created exists
        let parent = match path.dirname_str() {
            Some(p) => p,
            None => ""
        };
        let parent_exists = Path::new(parent).exists();
        if parent_exists && !path.exists() {
            // if mkdir failed return
            if !mkdir(&path, mode) {return;}
            if verbose {println!("{}", *dir);}
        } else {
            let mut error_msg = ~"";
            if !parent_exists {
                error_msg.push_str("Error: parent directory '");
                error_msg.push_str(parent);
                error_msg.push_str("' does not exist");
            } else {
                error_msg.push_str("Error: directory '");
                error_msg.push_str(*dir);
                error_msg.push_str("' already exists");
            }
            writeln!(&mut stderr() as &mut Writer,
                     "{}", error_msg);
            os::set_exit_status(1);
        }
    }
}

/**
 * Wrapper to catch errors, return false if failed
 */
fn mkdir(path: &Path, mode: u32) -> bool {
    match fs::mkdir(path, mode) {
        Ok(_) => true,
        Err(e) => {
            writeln!(&mut stderr() as &mut Writer,
                     "mkdir: test {}", e.to_str());
            os::set_exit_status(1);
            false
        }
    }
}
<commit_msg>mkdir: add -V option<commit_after>#[crate_id(name="mkdir", vers="1.0.0", author="Nicholas Juszczak")];

/**
 * This file is part of the uutils coreutils package.
 *
 * (c) Nicholas Juszczak <juszczakn@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern mod extra;

use std::os;
use std::io::{fs, stderr};
use std::num::strconv;
use extra::getopts::groups;

static VERSION: &'static str = "1.0.0";

/**
 * Handles option parsing
 */
fn main() {
    let args = os::args();

    let opts = ~[
        // Linux-specific options, not implemented
        // groups::optflag("Z", "context", "set SELinux secutiry context" +
        // " of each created directory to CTX"),
        groups::optopt("m", "mode", "set file mode", "755"),
        groups::optflag("p", "parents", "make parent directories as needed"),
        groups::optflag("v", "verbose",
                        "print a message for each printed directory"),
        groups::optflag("h", "help", "display this help"),
        groups::optflag("V", "version", "display this version")
    ];

    let matches = match groups::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut stderr() as &mut Writer,
                     "Invalid options\n{}", f.to_err_msg());
            os::set_exit_status(1);
            return;
        }
    };

    if args.len() == 1 || matches.opt_present("help") {
        print_help(opts);
        return;
    }
    if matches.opt_present("version") {
        println!("mkdir v{}", VERSION);
        return;
    }
    let verbose_flag = matches.opt_present("verbose");
    let mk_parents = matches.opt_present("parents");

    // Translate a ~str in octal form to u32, default to 755
    // Not tested on Windows
    let mode_match = matches.opts_str(&[~"mode"]);
    let mode: u32 = if mode_match.is_some() {
        let m = mode_match.unwrap();
        let res = strconv::from_str_common(m, 8, false, false, false,
                                           strconv::ExpNone,
                                           false, false);
        if res.is_some() {
            res.unwrap()
        } else {
            writeln!(&mut stderr() as &mut Writer,
                     "Error: no mode given");
            os::set_exit_status(1);
            return;
        }
    } else {
        0o755
    };

    let dirs = matches.free;
    exec(dirs, mk_parents, mode, verbose_flag);
}

fn print_help(opts: &[groups::OptGroup]) {
    println!("mkdir v{} - make a new directory with the given path", VERSION);
    println!("");
    println!("Usage:");
    print!("{}", groups::usage("Create the given DIRECTORY(ies)" +
                               " if they do not exist", opts));
}

/**
 * Create the list of new directories
 */
fn exec(dirs: ~[~str], mk_parents: bool, mode: u32, verbose: bool) {
    let mut parent_dirs: ~[~str] = ~[];
    if mk_parents {
        for dir in dirs.iter() {
            let path = Path::new((*dir).clone());
            // Build list of parent dirs which need to be created
            let parent = path.dirname_str();
            match parent {
                Some(p) => {
                    if !Path::new(p).exists() {
                        parent_dirs.push(p.into_owned())
                    }
                },
                None => ()
            }
        }
    }
    // Recursively build parent dirs that are needed
    if !parent_dirs.is_empty() {
        exec(parent_dirs, mk_parents, mode, verbose);
    }

    for dir in dirs.iter() {
        let path = Path::new((*dir).clone());
        // Determine if parent directory to the one to
        // be created exists
        let parent = match path.dirname_str() {
            Some(p) => p,
            None => ""
        };
        let parent_exists = Path::new(parent).exists();
        if parent_exists && !path.exists() {
            // if mkdir failed return
            if !mkdir(&path, mode) {return;}
            if verbose {println!("{}", *dir);}
        } else {
            let mut error_msg = ~"";
            if !parent_exists {
                error_msg.push_str("Error: parent directory '");
                error_msg.push_str(parent);
                error_msg.push_str("' does not exist");
            } else {
                error_msg.push_str("Error: directory '");
                error_msg.push_str(*dir);
                error_msg.push_str("' already exists");
            }
            writeln!(&mut stderr() as &mut Writer,
                     "{}", error_msg);
            os::set_exit_status(1);
        }
    }
}

/**
 * Wrapper to catch errors, return false if failed
 */
fn mkdir(path: &Path, mode: u32) -> bool {
    match fs::mkdir(path, mode) {
        Ok(_) => true,
        Err(e) => {
            writeln!(&mut stderr() as &mut Writer,
                     "mkdir: test {}", e.to_str());
            os::set_exit_status(1);
            false
        }
    }
}
<|endoftext|>


<commit_before>use super::{CellId, Mesh, PointId};
use crate::shapes::Shape;
use crate::StrError;
use russell_lab::{sort2, sort4};
use std::collections::HashMap;

/// Aliases (usize,usize) as the key of Edge
///
/// # Note
///
/// Since the local numbering scheme runs over "corners" first, we can compare
/// edges using only two points; i.e., the middle points don't matter.
pub type EdgeKey = (usize, usize);

/// Aliases (usize,usize,usize,usize) as the key of Face
///
/// # Note
///
/// If all faces have at most 3 points, the fourth entry in the key will be equal to the total number of points.
/// In this way, we can compare 4-node (or more nodes) faces with each other, since that the local numbering
/// scheme runs over the "corners" first; i.e., the middle points don't matter.
pub type FaceKey = (usize, usize, usize, usize);

/// Holds edge data (derived data structure)
#[derive(Clone, Debug)]
pub struct Edge {
    /// List of points defining this edge; in the right order (unsorted)
    pub points: Vec<PointId>,
}

/// Holds face data (derived data structure)
#[derive(Clone, Debug)]
pub struct Face {
    /// List of points defining this face; in the right order (unsorted)
    pub points: Vec<PointId>,
}

/// Extracts all edges (internal and boundary) in 2D
///
/// # Input
///
/// * `mesh` -- the Mesh
/// * `shapes` -- the shapes of cells (len == cells.len())
///
/// # Output
///
/// * Returns a map relating edge keys to `Vec<(cell_id, e)>` where:
///     - `cell_id` -- the id of the cell sharing the edge
///     - `e` -- is the cell's local edge index (or 0 if the cell.geo_ndim == 1)
pub fn all_edges_2d(mesh: &Mesh, shapes: &Vec<Shape>) -> Result<HashMap<EdgeKey, Vec<(CellId, usize)>>, StrError> {
    if mesh.space_ndim != 2 {
        return Err("this function works in 2D only");
    }
    let mut edges: HashMap<EdgeKey, Vec<(CellId, usize)>> = HashMap::new();
    mesh.cells.iter().zip(shapes).for_each(|(cell, shape)| {
        if shape.geo_ndim == 1 {
            let mut edge_key: EdgeKey = (cell.points[0], cell.points[1]);
            sort2(&mut edge_key);
            let data = edges.entry(edge_key).or_insert(Vec::new());
            data.push((cell.id, 0));
        }
        if shape.geo_ndim == 2 {
            for e in 0..shape.nedge {
                let mut edge_key: EdgeKey = (
                    cell.points[shape.edge_node_id(e, 0)],
                    cell.points[shape.edge_node_id(e, 1)],
                );
                sort2(&mut edge_key);
                let data = edges.entry(edge_key).or_insert(Vec::new());
                data.push((cell.id, e));
            }
        }
    });
    Ok(edges)
}

/// Extracts all faces (internal and boundary) in 3D
///
/// # Input
///
/// * `mesh` -- the Mesh
/// * `shapes` -- the shapes of cells (len == cells.len())
///
/// # Output
///
/// * Returns a map relating face keys to `Vec<(cell_id, f)>` where:
///     - `cell_id` -- the id of the cell sharing the face
///     - `f` -- is the cell's local face index (or 0 if the cell.geo_ndim == 1 or 2)
pub fn all_faces_3d(mesh: &Mesh, shapes: &Vec<Shape>) -> Result<HashMap<FaceKey, Vec<(CellId, usize)>>, StrError> {
    if mesh.space_ndim != 3 {
        return Err("this function works in 3D only");
    }
    let mut faces: HashMap<FaceKey, Vec<(CellId, usize)>> = HashMap::new();
    mesh.cells.iter().zip(shapes).for_each(|(cell, shape)| {
        if shape.geo_ndim == 2 {
            let mut face_key: FaceKey = if shape.nnode > 3 {
                (cell.points[0], cell.points[1], cell.points[2], cell.points[3])
            } else {
                (cell.points[0], cell.points[1], cell.points[2], mesh.points.len())
            };
            sort4(&mut face_key);
            let data = faces.entry(face_key).or_insert(Vec::new());
            data.push((cell.id, 0));
        }
        if shape.geo_ndim == 3 {
            for f in 0..shape.nface {
                let mut face_key: FaceKey = if shape.face_nnode > 3 {
                    (
                        cell.points[shape.face_node_id(f, 0)],
                        cell.points[shape.face_node_id(f, 1)],
                        cell.points[shape.face_node_id(f, 2)],
                        cell.points[shape.face_node_id(f, 3)],
                    )
                } else {
                    (
                        cell.points[shape.face_node_id(f, 0)],
                        cell.points[shape.face_node_id(f, 1)],
                        cell.points[shape.face_node_id(f, 2)],
                        mesh.points.len(),
                    )
                };
                sort4(&mut face_key);
                let data = faces.entry(face_key).or_insert(Vec::new());
                data.push((cell.id, f));
            }
        }
    });
    Ok(faces)
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::{all_edges_2d, all_faces_3d};
    use crate::mesh::{alloc_cell_shapes, Samples};
    use crate::StrError;

    #[test]
    fn all_edges_2d_works() -> Result<(), StrError> {
        //  3---------2---------5
        //  |         |         |
        //  |   [0]   |   [1]   |
        //  |         |         |
        //  0---------1---------4
        let mesh = Samples::two_quads_horizontal();
        let shapes = alloc_cell_shapes(&mesh)?;
        let edges = all_edges_2d(&mesh, &shapes)?;
        let mut keys: Vec<_> = edges.keys().collect();
        keys.sort();
        assert_eq!(keys, [&(0, 1), &(0, 3), &(1, 2), &(1, 4), &(2, 3), &(2, 5), &(4, 5)]);
        assert_eq!(edges.get(&(0, 1)).unwrap(), &[(0, 0)]);
        assert_eq!(edges.get(&(0, 3)).unwrap(), &[(0, 3)]);
        assert_eq!(edges.get(&(1, 2)).unwrap(), &[(0, 1), (1, 3)]);
        assert_eq!(edges.get(&(1, 4)).unwrap(), &[(1, 0)]);
        assert_eq!(edges.get(&(2, 3)).unwrap(), &[(0, 2)]);
        assert_eq!(edges.get(&(2, 5)).unwrap(), &[(1, 2)]);
        assert_eq!(edges.get(&(4, 5)).unwrap(), &[(1, 1)]);
        Ok(())
    }

    #[test]
    fn all_edges_2d_mixed_works() -> Result<(), StrError> {
        //           4---------3
        //           |         |
        //           |   [1]   |
        //           |         |
        //  0--------1---------2
        let mesh = Samples::mixed_shapes_2d();
        let shapes = alloc_cell_shapes(&mesh)?;
        let edges = all_edges_2d(&mesh, &shapes)?;
        let mut keys: Vec<_> = edges.keys().collect();
        keys.sort();
        assert_eq!(keys, [&(0, 1), &(1, 2), &(1, 4), &(2, 3), &(3, 4)]);
        assert_eq!(edges.get(&(0, 1)).unwrap(), &[(0, 0)]);
        assert_eq!(edges.get(&(1, 2)).unwrap(), &[(1, 0)]);
        assert_eq!(edges.get(&(1, 4)).unwrap(), &[(1, 3)]);
        assert_eq!(edges.get(&(2, 3)).unwrap(), &[(1, 1)]);
        assert_eq!(edges.get(&(3, 4)).unwrap(), &[(1, 2)]);
        Ok(())
    }

    #[test]
    fn all_faces_3d_works() -> Result<(), StrError> {
        //      8-------------11
        //     /.             /|
        //    / .            / |
        //   /  .           /  |
        //  /   .          /   |       id = 1
        // 9-------------10    |       attribute_id = 2
        // |    .         |    |
        // |    4---------|----7
        // |   /.         |   /|
        // |  / .         |  / |
        // | /  .         | /  |
        // |/   .         |/   |
        // 5--------------6    |       id = 0
        // |    .         |    |       attribute_id = 1
        // |    0---------|----3
        // |   /          |   /
        // |  /           |  /
        // | /            | /
        // |/             |/
        // 1--------------2
        let mesh = Samples::two_cubes_vertical();
        let shapes = alloc_cell_shapes(&mesh)?;
        let faces = all_faces_3d(&mesh, &shapes)?;
        let mut keys: Vec<_> = faces.keys().collect();
        keys.sort();
        assert_eq!(
            keys,
            [
                &(0, 1, 2, 3),
                &(0, 1, 4, 5),
                &(0, 3, 4, 7),
                &(1, 2, 5, 6),
                &(2, 3, 6, 7),
                &(4, 5, 6, 7),
                &(4, 5, 8, 9),
                &(4, 7, 8, 11),
                &(5, 6, 9, 10),
                &(6, 7, 10, 11),
                &(8, 9, 10, 11),
            ]
        );
        assert_eq!(faces.get(&(0, 1, 2, 3)).unwrap(), &[(0, 4)]);
        assert_eq!(faces.get(&(0, 1, 4, 5)).unwrap(), &[(0, 2)]);
        assert_eq!(faces.get(&(0, 3, 4, 7)).unwrap(), &[(0, 0)]);
        assert_eq!(faces.get(&(1, 2, 5, 6)).unwrap(), &[(0, 1)]);
        assert_eq!(faces.get(&(2, 3, 6, 7)).unwrap(), &[(0, 3)]);
        assert_eq!(faces.get(&(4, 5, 6, 7)).unwrap(), &[(0, 5), (1, 4)]);
        assert_eq!(faces.get(&(4, 5, 8, 9)).unwrap(), &[(1, 2)]);
        assert_eq!(faces.get(&(4, 7, 8, 11)).unwrap(), &[(1, 0)]);
        assert_eq!(faces.get(&(5, 6, 9, 10)).unwrap(), &[(1, 1)]);
        assert_eq!(faces.get(&(6, 7, 10, 11)).unwrap(), &[(1, 3)]);
        assert_eq!(faces.get(&(8, 9, 10, 11)).unwrap(), &[(1, 5)]);
        Ok(())
    }

    #[test]
    fn all_faces_3d_mixed_works() -> Result<(), StrError> {
        //                       4------------7-----------10
        //                      /.           /|            |
        //                     / .          / |            |
        //                    /  .         /  |            |
        //                   /   .        /   |            |
        //                  5------------6    |            |
        //                  |    .       |`.  |            |
        //                  |    0-------|--`.3------------9
        //                  |   /        |   /`.          /
        //                  |  /         |  /   `.       /
        //                  | /          | /      `.    /
        //                  |/           |/         `. /
        //  12-----11-------1------------2------------8
        //
        let mesh = Samples::mixed_shapes_3d();
        let shapes = alloc_cell_shapes(&mesh)?;
        let faces = all_faces_3d(&mesh, &shapes)?;
        let mut keys: Vec<_> = faces.keys().collect();
        keys.sort();
        assert_eq!(
            keys,
            [
                &(0, 1, 2, 3),
                &(0, 1, 4, 5),
                &(0, 3, 4, 7),
                &(1, 2, 5, 6),
                &(2, 3, 6, 7),
                &(2, 3, 6, 13),
                &(2, 3, 8, 13),
                &(2, 6, 8, 13),
                &(3, 6, 8, 13),
                &(3, 7, 9, 10),
                &(3, 8, 9, 13),
                &(4, 5, 6, 7),
            ]
        );
        assert_eq!(faces.get(&(0, 1, 2, 3)).unwrap(), &[(0, 4)]);
        assert_eq!(faces.get(&(0, 1, 4, 5)).unwrap(), &[(0, 2)]);
        assert_eq!(faces.get(&(0, 3, 4, 7)).unwrap(), &[(0, 0)]);
        assert_eq!(faces.get(&(1, 2, 5, 6)).unwrap(), &[(0, 1)]);
        assert_eq!(faces.get(&(2, 3, 6, 7)).unwrap(), &[(0, 3)]);
        assert_eq!(faces.get(&(2, 3, 6, 13)).unwrap(), &[(1, 0)]);
        assert_eq!(faces.get(&(2, 3, 8, 13)).unwrap(), &[(1, 2)]);
        assert_eq!(faces.get(&(2, 6, 8, 13)).unwrap(), &[(1, 1)]);
        assert_eq!(faces.get(&(3, 6, 8, 13)).unwrap(), &[(1, 3)]);
        assert_eq!(faces.get(&(3, 7, 9, 10)).unwrap(), &[(2, 0)]);
        assert_eq!(faces.get(&(3, 8, 9, 13)).unwrap(), &[(3, 0)]);
        assert_eq!(faces.get(&(4, 5, 6, 7)).unwrap(), &[(0, 5)]);
        Ok(())
    }
}
<commit_msg>Improve comments<commit_after>use super::{CellId, Mesh, PointId};
use crate::shapes::Shape;
use crate::StrError;
use russell_lab::{sort2, sort4};
use std::collections::HashMap;

/// Aliases (usize,usize) as the key of edges
///
/// # Note
///
/// Since the local numbering scheme runs over "corners" first, we can compare
/// edges using only two points; i.e., the middle points don't matter.
pub type EdgeKey = (usize, usize);

/// Aliases (usize,usize,usize,usize) as the key of faces
///
/// # Note
///
/// If a face has at most 3 points, the fourth entry in the key will be set to the total number of points.
/// In this way, we can compare 4-node (or more nodes) faces with each other. Since the local numbering
/// scheme runs over the "corners" first, the middle points don't matter.
pub type FaceKey = (usize, usize, usize, usize);

/// Holds the point ids of an edge (an entity belonging to a cell in 2D or a face in 3D)
#[derive(Clone, Debug)]
pub struct Edge {
    /// List of points defining this edge; in the right order (unsorted)
    pub points: Vec<PointId>,
}

/// Holds the point ids of a face (an entity belonging to a cell in 3D)
#[derive(Clone, Debug)]
pub struct Face {
    /// List of points defining this face; in the right order (unsorted)
    pub points: Vec<PointId>,
}

/// Extracts all edges (internal and boundary) in 2D
///
/// # Input
///
/// * `mesh` -- the Mesh
/// * `shapes` -- the shapes of cells (len == cells.len())
///
/// # Output
///
/// * Returns a map relating edge keys to `Vec<(cell_id, e)>` where:
///     - `cell_id` -- the id of the cell sharing the edge
///     - `e` -- is the cell's local edge index (or 0 if the cell.geo_ndim == 1)
pub fn all_edges_2d(mesh: &Mesh, shapes: &Vec<Shape>) -> Result<HashMap<EdgeKey, Vec<(CellId, usize)>>, StrError> {
    if mesh.space_ndim != 2 {
        return Err("this function works in 2D only");
    }
    let mut edges: HashMap<EdgeKey, Vec<(CellId, usize)>> = HashMap::new();
    mesh.cells.iter().zip(shapes).for_each(|(cell, shape)| {
        if shape.geo_ndim == 1 {
            let mut edge_key: EdgeKey = (cell.points[0], cell.points[1]);
            sort2(&mut edge_key);
            let data = edges.entry(edge_key).or_insert(Vec::new());
            data.push((cell.id, 0));
        }
        if shape.geo_ndim == 2 {
            for e in 0..shape.nedge {
                let mut edge_key: EdgeKey = (
                    cell.points[shape.edge_node_id(e, 0)],
                    cell.points[shape.edge_node_id(e, 1)],
                );
                sort2(&mut edge_key);
                let data = edges.entry(edge_key).or_insert(Vec::new());
                data.push((cell.id, e));
            }
        }
    });
    Ok(edges)
}

/// Extracts all faces (internal and boundary) in 3D
///
/// # Input
///
/// * `mesh` -- the Mesh
/// * `shapes` -- the shapes of cells (len == cells.len())
///
/// # Output
///
/// * Returns a map relating face keys to `Vec<(cell_id, f)>` where:
///     - `cell_id` -- the id of the cell sharing the face
///     - `f` -- is the cell's local face index (or 0 if the cell.geo_ndim == 1 or 2)
pub fn all_faces_3d(mesh: &Mesh, shapes: &Vec<Shape>) -> Result<HashMap<FaceKey, Vec<(CellId, usize)>>, StrError> {
    if mesh.space_ndim != 3 {
        return Err("this function works in 3D only");
    }
    let mut faces: HashMap<FaceKey, Vec<(CellId, usize)>> = HashMap::new();
    mesh.cells.iter().zip(shapes).for_each(|(cell, shape)| {
        if shape.geo_ndim == 2 {
            let mut face_key: FaceKey = if shape.nnode > 3 {
                (cell.points[0], cell.points[1], cell.points[2], cell.points[3])
            } else {
                (cell.points[0], cell.points[1], cell.points[2], mesh.points.len())
            };
            sort4(&mut face_key);
            let data = faces.entry(face_key).or_insert(Vec::new());
            data.push((cell.id, 0));
        }
        if shape.geo_ndim == 3 {
            for f in 0..shape.nface {
                let mut face_key: FaceKey = if shape.face_nnode > 3 {
                    (
                        cell.points[shape.face_node_id(f, 0)],
                        cell.points[shape.face_node_id(f, 1)],
                        cell.points[shape.face_node_id(f, 2)],
                        cell.points[shape.face_node_id(f, 3)],
                    )
                } else {
                    (
                        cell.points[shape.face_node_id(f, 0)],
                        cell.points[shape.face_node_id(f, 1)],
                        cell.points[shape.face_node_id(f, 2)],
                        mesh.points.len(),
                    )
                };
                sort4(&mut face_key);
                let data = faces.entry(face_key).or_insert(Vec::new());
                data.push((cell.id, f));
            }
        }
    });
    Ok(faces)
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::{all_edges_2d, all_faces_3d};
    use crate::mesh::{alloc_cell_shapes, Samples};
    use crate::StrError;

    #[test]
    fn all_edges_2d_works() -> Result<(), StrError> {
        //  3---------2---------5
        //  |         |         |
        //  |   [0]   |   [1]   |
        //  |         |         |
        //  0---------1---------4
        let mesh = Samples::two_quads_horizontal();
        let shapes = alloc_cell_shapes(&mesh)?;
        let edges = all_edges_2d(&mesh, &shapes)?;
        let mut keys: Vec<_> = edges.keys().collect();
        keys.sort();
        assert_eq!(keys, [&(0, 1), &(0, 3), &(1, 2), &(1, 4), &(2, 3), &(2, 5), &(4, 5)]);
        assert_eq!(edges.get(&(0, 1)).unwrap(), &[(0, 0)]);
        assert_eq!(edges.get(&(0, 3)).unwrap(), &[(0, 3)]);
        assert_eq!(edges.get(&(1, 2)).unwrap(), &[(0, 1), (1, 3)]);
        assert_eq!(edges.get(&(1, 4)).unwrap(), &[(1, 0)]);
        assert_eq!(edges.get(&(2, 3)).unwrap(), &[(0, 2)]);
        assert_eq!(edges.get(&(2, 5)).unwrap(), &[(1, 2)]);
        assert_eq!(edges.get(&(4, 5)).unwrap(), &[(1, 1)]);
        Ok(())
    }

    #[test]
    fn all_edges_2d_mixed_works() -> Result<(), StrError> {
        //           4---------3
        //           |         |
        //           |   [1]   |
        //           |         |
        //  0--------1---------2
        let mesh = Samples::mixed_shapes_2d();
        let shapes = alloc_cell_shapes(&mesh)?;
        let edges = all_edges_2d(&mesh, &shapes)?;
        let mut keys: Vec<_> = edges.keys().collect();
        keys.sort();
        assert_eq!(keys, [&(0, 1), &(1, 2), &(1, 4), &(2, 3), &(3, 4)]);
        assert_eq!(edges.get(&(0, 1)).unwrap(), &[(0, 0)]);
        assert_eq!(edges.get(&(1, 2)).unwrap(), &[(1, 0)]);
        assert_eq!(edges.get(&(1, 4)).unwrap(), &[(1, 3)]);
        assert_eq!(edges.get(&(2, 3)).unwrap(), &[(1, 1)]);
        assert_eq!(edges.get(&(3, 4)).unwrap(), &[(1, 2)]);
        Ok(())
    }

    #[test]
    fn all_faces_3d_works() -> Result<(), StrError> {
        //      8-------------11
        //     /.             /|
        //    / .            / |
        //   /  .           /  |
        //  /   .          /   |       id = 1
        // 9-------------10    |       attribute_id = 2
        // |    .         |    |
        // |    4---------|----7
        // |   /.         |   /|
        // |  / .         |  / |
        // | /  .         | /  |
        // |/   .         |/   |
        // 5--------------6    |       id = 0
        // |    .         |    |       attribute_id = 1
        // |    0---------|----3
        // |   /          |   /
        // |  /           |  /
        // | /            | /
        // |/             |/
        // 1--------------2
        let mesh = Samples::two_cubes_vertical();
        let shapes = alloc_cell_shapes(&mesh)?;
        let faces = all_faces_3d(&mesh, &shapes)?;
        let mut keys: Vec<_> = faces.keys().collect();
        keys.sort();
        assert_eq!(
            keys,
            [
                &(0, 1, 2, 3),
                &(0, 1, 4, 5),
                &(0, 3, 4, 7),
                &(1, 2, 5, 6),
                &(2, 3, 6, 7),
                &(4, 5, 6, 7),
                &(4, 5, 8, 9),
                &(4, 7, 8, 11),
                &(5, 6, 9, 10),
                &(6, 7, 10, 11),
                &(8, 9, 10, 11),
            ]
        );
        assert_eq!(faces.get(&(0, 1, 2, 3)).unwrap(), &[(0, 4)]);
        assert_eq!(faces.get(&(0, 1, 4, 5)).unwrap(), &[(0, 2)]);
        assert_eq!(faces.get(&(0, 3, 4, 7)).unwrap(), &[(0, 0)]);
        assert_eq!(faces.get(&(1, 2, 5, 6)).unwrap(), &[(0, 1)]);
        assert_eq!(faces.get(&(2, 3, 6, 7)).unwrap(), &[(0, 3)]);
        assert_eq!(faces.get(&(4, 5, 6, 7)).unwrap(), &[(0, 5), (1, 4)]);
        assert_eq!(faces.get(&(4, 5, 8, 9)).unwrap(), &[(1, 2)]);
        assert_eq!(faces.get(&(4, 7, 8, 11)).unwrap(), &[(1, 0)]);
        assert_eq!(faces.get(&(5, 6, 9, 10)).unwrap(), &[(1, 1)]);
        assert_eq!(faces.get(&(6, 7, 10, 11)).unwrap(), &[(1, 3)]);
        assert_eq!(faces.get(&(8, 9, 10, 11)).unwrap(), &[(1, 5)]);
        Ok(())
    }

    #[test]
    fn all_faces_3d_mixed_works() -> Result<(), StrError> {
        //                       4------------7-----------10
        //                      /.           /|            |
        //                     / .          / |            |
        //                    /  .         /  |            |
        //                   /   .        /   |            |
        //                  5------------6    |            |
        //                  |    .       |`.  |            |
        //                  |    0-------|--`.3------------9
        //                  |   /        |   /`.          /
        //                  |  /         |  /   `.       /
        //                  | /          | /      `.    /
        //                  |/           |/         `. /
        //  12-----11-------1------------2------------8
        //
        let mesh = Samples::mixed_shapes_3d();
        let shapes = alloc_cell_shapes(&mesh)?;
        let faces = all_faces_3d(&mesh, &shapes)?;
        let mut keys: Vec<_> = faces.keys().collect();
        keys.sort();
        assert_eq!(
            keys,
            [
                &(0, 1, 2, 3),
                &(0, 1, 4, 5),
                &(0, 3, 4, 7),
                &(1, 2, 5, 6),
                &(2, 3, 6, 7),
                &(2, 3, 6, 13),
                &(2, 3, 8, 13),
                &(2, 6, 8, 13),
                &(3, 6, 8, 13),
                &(3, 7, 9, 10),
                &(3, 8, 9, 13),
                &(4, 5, 6, 7),
            ]
        );
        assert_eq!(faces.get(&(0, 1, 2, 3)).unwrap(), &[(0, 4)]);
        assert_eq!(faces.get(&(0, 1, 4, 5)).unwrap(), &[(0, 2)]);
        assert_eq!(faces.get(&(0, 3, 4, 7)).unwrap(), &[(0, 0)]);
        assert_eq!(faces.get(&(1, 2, 5, 6)).unwrap(), &[(0, 1)]);
        assert_eq!(faces.get(&(2, 3, 6, 7)).unwrap(), &[(0, 3)]);
        assert_eq!(faces.get(&(2, 3, 6, 13)).unwrap(), &[(1, 0)]);
        assert_eq!(faces.get(&(2, 3, 8, 13)).unwrap(), &[(1, 2)]);
        assert_eq!(faces.get(&(2, 6, 8, 13)).unwrap(), &[(1, 1)]);
        assert_eq!(faces.get(&(3, 6, 8, 13)).unwrap(), &[(1, 3)]);
        assert_eq!(faces.get(&(3, 7, 9, 10)).unwrap(), &[(2, 0)]);
        assert_eq!(faces.get(&(3, 8, 9, 13)).unwrap(), &[(3, 0)]);
        assert_eq!(faces.get(&(4, 5, 6, 7)).unwrap(), &[(0, 5)]);
        Ok(())
    }
}
<|endoftext|>


<commit_before>#![no_std]
#![feature(no_std)]
#![feature(core, core_prelude, core_slice_ext, slice_bytes)]

#[macro_use]
extern crate core;

use core::prelude::*;
use core::cmp::min;
use core::slice::bytes::copy_memory;

#[macro_export]
macro_rules! try {
	($expr:expr) => (match $expr {
		core::result::Result::Ok(val) => val,
		core::result::Result::Err(err) => {
			return core::result::Result::Err(core::convert::From::from(err))
		}
	})
}

#[derive(Copy, Clone, Debug)]
pub struct EndOfFile;

#[derive(Copy, Clone, Debug)]
pub struct OutOfBounds;

pub trait Read {
	type Err;

	fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Err>;

	fn read_all<E=<Self as Read>::Err>(&mut self, buf: &mut [u8]) -> Result<(), E> where E: From<Self::Err> + From<EndOfFile> {
		let mut offset = 0;
		while offset < buf.len() {
			match try!(self.read(&mut buf[offset..])) {
				0 => return Err(E::from(EndOfFile)),
				n => offset += n
			}
		}
		Ok(())
	}
}

pub trait Write {
	type Err;

	fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Err>;

	fn write_all<E=<Self as Write>::Err>(&mut self, mut buf: &[u8]) -> Result<(), E> where E: From<Self::Err> + From<EndOfFile> {
		while buf.len() > 0 {
			match try!(self.write(buf)) {
				0 => return Err(E::from(EndOfFile)),
				n => buf = &buf[n..]
			}
		}
		Ok(())
	}
}

pub enum SeekFrom {
	Start(u64),
	End(i64),
	Current(i64),
}

pub trait Seek {
	type Err;

	fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Err>;

	fn tell(&mut self) -> Result<u64, Self::Err> {
		self.seek(SeekFrom::Current(0))
	}
}

impl<'a> Read for &'a [u8] {
	type Err = EndOfFile;

	fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Err> {
		let len = min(buf.len(), self.len());
		if len == 0 {
			return Err(EndOfFile)
		}
		let (a, b) = self.split_at(len);
		copy_memory(a, buf);
		*self = b;
		Ok(len)
	}
}

pub struct Cursor<T> {
	inner: T,
	pos: u64
}

impl<T> Cursor<T> {
	pub fn new(inner: T) -> Cursor<T> {
		Cursor {
			inner: inner,
			pos: 0
		}
	}
}

impl<'a> Read for Cursor<&'a [u8]> {
	type Err = EndOfFile;

	fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndOfFile> {
		let len = try!((&self.inner[self.pos as usize..]).read(buf));
		self.pos += len as u64;
		Ok(len)
	}
}

impl<'a> Seek for Cursor<&'a [u8]> {
	type Err = OutOfBounds;

	fn seek(&mut self, from: SeekFrom) -> Result<u64, OutOfBounds> {
		let pos = match from {
			SeekFrom::Start(offset) => offset as i64,
			SeekFrom::End(offset) => self.inner.len() as i64 + offset as i64,
			SeekFrom::Current(offset) => self.pos as i64 + offset
		};
		if pos < 0 {
			return Err(OutOfBounds);
		}
		self.pos = min(pos as u64, self.inner.len() as u64);
		Ok(self.pos)
	}
}

impl<'a, R: Read> Read for &'a mut R {
	type Err = R::Err;

	fn read(&mut self, buf: &mut [u8]) -> Result<usize, R::Err> {
		(**self).read(buf)
	}

	fn read_all<E=<Self as Read>::Err>(&mut self, buf: &mut [u8]) -> Result<(), E> where E: From<R::Err> + From<EndOfFile> {
		(**self).read_all(buf)
	}
}

impl<'a, W: Write> Write for &'a mut W {
	type Err = W::Err;

	fn write(&mut self, buf: &[u8]) -> Result<usize, W::Err> {
		(**self).write(buf)
	}

	fn write_all<E=<Self as Write>::Err>(&mut self, buf: &[u8]) -> Result<(), E> where E: From<W::Err> + From<EndOfFile> {
		(**self).write_all(buf)
	}
}

impl<'a, S: Seek> Seek for &'a mut S {
	type Err = S::Err;

	fn seek(&mut self, pos: SeekFrom) -> Result<u64, S::Err> {
		(**self).seek(pos)
	}

	fn tell(&mut self) -> Result<u64, S::Err> {
		(**self).tell()
	}
}
<commit_msg>Fix the embedded try! macro<commit_after>#![no_std]
#![feature(no_std)]
#![feature(core, core_prelude, core_slice_ext, slice_bytes)]

#[macro_use]
extern crate core;

use core::prelude::*;
use core::cmp::min;
use core::slice::bytes::copy_memory;

#[macro_export]
macro_rules! try {
	($expr:expr) => (match $expr {
		::core::result::Result::Ok(val) => val,
		::core::result::Result::Err(err) => {
			return ::core::result::Result::Err(::core::convert::From::from(err))
		}
	})
}

#[derive(Copy, Clone, Debug)]
pub struct EndOfFile;

#[derive(Copy, Clone, Debug)]
pub struct OutOfBounds;

pub trait Read {
	type Err;

	fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Err>;

	fn read_all<E=<Self as Read>::Err>(&mut self, buf: &mut [u8]) -> Result<(), E> where E: From<Self::Err> + From<EndOfFile> {
		let mut offset = 0;
		while offset < buf.len() {
			match try!(self.read(&mut buf[offset..])) {
				0 => return Err(E::from(EndOfFile)),
				n => offset += n
			}
		}
		Ok(())
	}
}

pub trait Write {
	type Err;

	fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Err>;

	fn write_all<E=<Self as Write>::Err>(&mut self, mut buf: &[u8]) -> Result<(), E> where E: From<Self::Err> + From<EndOfFile> {
		while buf.len() > 0 {
			match try!(self.write(buf)) {
				0 => return Err(E::from(EndOfFile)),
				n => buf = &buf[n..]
			}
		}
		Ok(())
	}
}

pub enum SeekFrom {
	Start(u64),
	End(i64),
	Current(i64),
}

pub trait Seek {
	type Err;

	fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Err>;

	fn tell(&mut self) -> Result<u64, Self::Err> {
		self.seek(SeekFrom::Current(0))
	}
}

impl<'a> Read for &'a [u8] {
	type Err = EndOfFile;

	fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Err> {
		let len = min(buf.len(), self.len());
		if len == 0 {
			return Err(EndOfFile)
		}
		let (a, b) = self.split_at(len);
		copy_memory(a, buf);
		*self = b;
		Ok(len)
	}
}

pub struct Cursor<T> {
	inner: T,
	pos: u64
}

impl<T> Cursor<T> {
	pub fn new(inner: T) -> Cursor<T> {
		Cursor {
			inner: inner,
			pos: 0
		}
	}
}

impl<'a> Read for Cursor<&'a [u8]> {
	type Err = EndOfFile;

	fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndOfFile> {
		let len = try!((&self.inner[self.pos as usize..]).read(buf));
		self.pos += len as u64;
		Ok(len)
	}
}

impl<'a> Seek for Cursor<&'a [u8]> {
	type Err = OutOfBounds;

	fn seek(&mut self, from: SeekFrom) -> Result<u64, OutOfBounds> {
		let pos = match from {
			SeekFrom::Start(offset) => offset as i64,
			SeekFrom::End(offset) => self.inner.len() as i64 + offset as i64,
			SeekFrom::Current(offset) => self.pos as i64 + offset
		};
		if pos < 0 {
			return Err(OutOfBounds);
		}
		self.pos = min(pos as u64, self.inner.len() as u64);
		Ok(self.pos)
	}
}

impl<'a, R: Read> Read for &'a mut R {
	type Err = R::Err;

	fn read(&mut self, buf: &mut [u8]) -> Result<usize, R::Err> {
		(**self).read(buf)
	}

	fn read_all<E=<Self as Read>::Err>(&mut self, buf: &mut [u8]) -> Result<(), E> where E: From<R::Err> + From<EndOfFile> {
		(**self).read_all(buf)
	}
}

impl<'a, W: Write> Write for &'a mut W {
	type Err = W::Err;

	fn write(&mut self, buf: &[u8]) -> Result<usize, W::Err> {
		(**self).write(buf)
	}

	fn write_all<E=<Self as Write>::Err>(&mut self, buf: &[u8]) -> Result<(), E> where E: From<W::Err> + From<EndOfFile> {
		(**self).write_all(buf)
	}
}

impl<'a, S: Seek> Seek for &'a mut S {
	type Err = S::Err;

	fn seek(&mut self, pos: SeekFrom) -> Result<u64, S::Err> {
		(**self).seek(pos)
	}

	fn tell(&mut self) -> Result<u64, S::Err> {
		(**self).tell()
	}
}
<|endoftext|>


<commit_before>#![feature(test)]
#![feature(step_by)]
extern crate raw_nbits_vec;
extern crate test;
extern crate num;

mod tests {
    macro_rules! bench_test {
        ($(($m: ident, $nbits: ident, $storage: ident)),*) => {
            mod get {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            let n = test::black_box(100);
                            let mut vec: NbitsVec<$nbits, $storage> = NbitsVec::with_capacity(n);
                            unsafe { vec.set_len(n) }
                            b.iter(|| {
                                (0..n).fold(0, |_a, i| vec.get(i));
                            })
                        }
                    }
                )*
            }
            mod resize {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        use num::Zero;
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            let n = test::black_box(100);
                            let mut vec: NbitsVec<$nbits, $storage> = NbitsVec::new();
                            b.iter(|| {
                                for i in (0..n).step_by(10) {
                                    vec.resize(i, $storage::zero());
                                }
                            })
                        }
                    }
                )*
            }
            mod set {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            b.iter(|| {
                                let n = test::black_box(100);
                                let mut vec: NbitsVec<As1bits> = NbitsVec::with_capacity(n);
                                unsafe { vec.set_len(n) };
                                for i in 0..n {
                                    vec.set(i, i);
                                }
                            });
                        }
                    }
                )*
            }
            mod new {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            b.iter(|| {
                                let n = test::black_box(100);
                                let vec: NbitsVec<As1bits> = NbitsVec::with_capacity(n);
                                vec
                            });
                        }
                    }
                 )*
            }
            mod push {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn set(b: &mut Bencher) {
                            b.iter(|| {
                                let n = test::black_box(100);
                                let mut vec: NbitsVec<As1bits> = NbitsVec::with_capacity(n);
                                for i in 0..n {
                                    vec.push(i)
                                }
                            });
                        }
                    }
                 )*
            }
        }
    }
    bench_test! {
        (test_4bits_usize, As4bits, usize),
        (test_4bits_u64, As4bits, u64),
        (test_4bits_u32, As4bits, u32),
        (test_4bits_u16, As4bits, u16),
        (test_4bits_u8, As4bits, u8),
        (test_3bits_usize, As3bits, usize),
        (test_3bits_u64, As3bits, u64),
        (test_3bits_u32, As3bits, u32),
        (test_3bits_u16, As3bits, u16),
        (test_3bits_u8, As3bits, u8),
        (test_2bits_usize, As2bits, usize),
        (test_2bits_u64, As2bits, u64),
        (test_2bits_u32, As2bits, u32),
        (test_2bits_u16, As2bits, u16),
        (test_2bits_u8, As2bits, u8),
        (test_1bits_usize, As1bits, usize),
        (test_1bits_u64, As1bits, u64),
        (test_1bits_u32, As1bits, u32),
        (test_1bits_u16, As1bits, u16),
        (test_1bits_u8, As1bits, u8)
    }
}
<commit_msg>Modify bench tests<commit_after>#![feature(test)]
#![feature(step_by)]
extern crate raw_nbits_vec;
extern crate test;
extern crate num;

mod tests {
    macro_rules! bench_test {
        ($(($m: ident, $nbits: ident, $storage: ident)),*) => {
            mod get {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            let n = test::black_box(100);
                            let mut vec: NbitsVec<$nbits, $storage> = NbitsVec::with_capacity(n);
                            unsafe { vec.set_len(n) }
                            b.iter(|| {
                                (0..n).fold(0, |_a, i| vec.get(i));
                            })
                        }
                    }
                )*
            }
            mod resize {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        use num::Zero;
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            let n = test::black_box(100);
                            let mut vec: NbitsVec<$nbits, $storage> = NbitsVec::new();
                            b.iter(|| {
                                for i in (0..n).step_by(10) {
                                    vec.resize(i, $storage::zero());
                                }
                            })
                        }
                    }
                )*
            }
            mod set {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            b.iter(|| {
                                let n = test::black_box(100);
                                let mut vec: NbitsVec<As1bits> = NbitsVec::with_capacity(n);
                                unsafe { vec.set_len(n) };
                                for i in 0..n {
                                    vec.set(i, i);
                                }
                            });
                        }
                    }
                )*
            }
            mod new {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            b.iter(|| {
                                let n = test::black_box(100);
                                let vec: NbitsVec<As1bits> = NbitsVec::with_capacity(n);
                                vec
                            });
                        }
                    }
                 )*
            }
            mod push {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn push(b: &mut Bencher) {
                            let n = test::black_box(100);
                            let mut vec: NbitsVec<As1bits> = NbitsVec::with_capacity(n);
                            b.iter(|| {
                                for i in 0..n {
                                    vec.push(i)
                                }
                            });
                        }
                    }
                 )*
            }
        }
    }
    bench_test! {
        (test_4bits_usize, As4bits, usize),
        (test_4bits_u64, As4bits, u64),
        (test_4bits_u32, As4bits, u32),
        (test_4bits_u16, As4bits, u16),
        (test_4bits_u8, As4bits, u8),
        (test_3bits_usize, As3bits, usize),
        (test_3bits_u64, As3bits, u64),
        (test_3bits_u32, As3bits, u32),
        (test_3bits_u16, As3bits, u16),
        (test_3bits_u8, As3bits, u8),
        (test_2bits_usize, As2bits, usize),
        (test_2bits_u64, As2bits, u64),
        (test_2bits_u32, As2bits, u32),
        (test_2bits_u16, As2bits, u16),
        (test_2bits_u8, As2bits, u8),
        (test_1bits_usize, As1bits, usize),
        (test_1bits_u64, As1bits, u64),
        (test_1bits_u32, As1bits, u32),
        (test_1bits_u16, As1bits, u16),
        (test_1bits_u8, As1bits, u8)
    }
}
<|endoftext|>