<commit_before>use utils::lru_cache::LRUCache;
use dovahkiin::types::custom_types::id::Id;
use dovahkiin::types::custom_types::map::Map;
use std::cell::RefCell;
use ram::cell::Cell;
use ram::types::*;
use std::cell::Ref;
use std::cell::RefMut;
use index::btree::*;
use bifrost::utils::async_locks::{RwLock, RwLockWriteGuard, RwLockReadGuard, Mutex};
use std::ops::Deref;
use std::ops::DerefMut;
use core::borrow::BorrowMut;
use dovahkiin::types::value::ToValue;
use itertools::Itertools;
use std::collections::BTreeMap;
use std::mem;
use std::rc::Rc;
use owning_ref::{RcRef, OwningHandle, OwningRef};
use ram::schema::{Schema, Field};
use dovahkiin::types::type_id_of;
use std::sync::Arc;
use client::AsyncClient;
use futures::Future;

pub type ExtNodeCacheMap = Mutex<LRUCache<Id, RwLock<ExtNode>>>;
pub type ExtNodeCachedMut = RwLockWriteGuard<ExtNode>;
pub type ExtNodeCachedImmute = RwLockReadGuard<ExtNode>;

const PAGE_SCHEMA: &'static str = "NEB_BTREE_PAGE";
const KEYS_FIELD: &'static str = "keys";
const NEXT_FIELD: &'static str = "next";
const PREV_FIELD: &'static str = "prev";

lazy_static! {
    static ref KEYS_KEY_HASH : u64 = key_hash(KEYS_FIELD);
    static ref NEXT_PAGE_KEY_HASH : u64 = key_hash(NEXT_FIELD);
    static ref PREV_PAGE_KEY_HASH : u64 = key_hash(PREV_FIELD);
    static ref PAGE_SCHEMA_ID: u32 = key_hash(PAGE_SCHEMA) as u32;
}

#[derive(Clone)]
pub struct ExtNode {
    pub id: Id,
    pub keys: EntryKeySlice,
    pub next: Id,
    pub prev: Id,
    pub len: usize,
    pub version: u64,
    pub removed: bool,
}

pub struct ExtNodeSplit {
    pub node_2: ExtNode,
    pub keys_1_len: usize
}

impl ExtNode {
    pub fn new(id: &Id) -> ExtNode {
        ExtNode {
            id: *id,
            keys: EntryKeySlice::init(),
            next: Id::unit_id(),
            prev: Id::unit_id(),
            len: 0,
            version: 0,
            removed: false
        }
    }
    pub fn from_cell(cell: Cell) -> Self {
        let keys = &cell.data[*KEYS_KEY_HASH];
        let keys_len = keys.len().unwrap();
        let mut key_slice = EntryKeySlice::init();
        let mut key_count = 0;
        let next = cell.data[*NEXT_PAGE_KEY_HASH].Id().unwrap();
        let prev = cell.data[*PREV_PAGE_KEY_HASH].Id().unwrap();
        for (i, key_val) in keys.iter_value().unwrap().enumerate() {
            let key = if let Value::PrimArray(PrimitiveArray::U8(ref array)) = key_val {
                EntryKey::from_slice(array.as_slice())
            } else { panic!("invalid entry") };
            key_slice[i] = key;
            key_count += 1;
        }
        ExtNode {
            id: cell.id(),
            keys: key_slice,
            next: *next,
            prev: *prev,
            len: key_count,
            version: cell.header.version,
            removed: false
        }
    }
    pub fn to_cell(&self) -> Cell {
        let mut value = Value::Map(Map::new());
        value[*NEXT_PAGE_KEY_HASH] = Value::Id(self.next);
        value[*KEYS_KEY_HASH] = self
            .keys[..self.len]
            .iter()
            .map(|key| {
                key.as_slice().to_vec().value()
            })
            .collect_vec()
            .value();
        Cell::new_with_id(*PAGE_SCHEMA_ID, &self.id, value)
    }
    pub fn remove(&mut self, pos: usize) {
        let cached_len = self.len;
        self.keys.remove_at(pos, cached_len);
        self.len -= 1;
    }
    pub fn insert(
        &mut self,
        key: EntryKey,
        pos: usize,
        tree: &BPlusTree,
        bz: &CacheBufferZone)
        -> Option<(Node, Option<EntryKey>)>
    {
        let mut cached = self;
        let cached_len = cached.len;
        if cached_len + 1 >= NUM_KEYS {
            // need to split
            debug!("insert to external with split");
            cached.dump();
            let pivot = cached_len / 2;
            let split = {
                let cached_next = *&cached.next;
                let cached_id = *&cached.id;
                let new_page_id = tree.new_page_id();
                cached.next = new_page_id;
                let mut keys_1 = &mut cached.keys;
                let mut keys_2 = keys_1.split_at_pivot(pivot, cached_len);
                let mut keys_1_len = pivot;
                let mut keys_2_len = cached_len - pivot;
                insert_into_split(
                    key,
                    keys_1, &mut keys_2,
                    &mut keys_1_len, &mut keys_2_len,
                    pos, pivot);
                ExtNodeSplit {
                    keys_1_len,
                    node_2: ExtNode {
                        id: new_page_id,
                        keys: keys_2,
                        next: cached_next,
                        prev: cached_id,
                        len: keys_2_len,
                        version: 0,
                        removed: false
                    }
                }
            };
            cached.next = split.node_2.id;
            cached.len = split.keys_1_len;
            let node_2_id = split.node_2.id;
            let node_2 = Node::External(box node_2_id);
            debug!("Split to left len {}, right len {}", cached.len, split.node_2.len);
            cached.dump();
            split.node_2.dump();
            bz.new_node(split.node_2);
            return Some((node_2, None));

        } else {
            debug!("insert to external without split at {}, key {:?}", pos, key);
            cached.keys.insert_at(key, pos, cached_len);
            cached.len += 1;
            return None;
        }
    }
    pub fn merge_with(&mut self, right: &mut Self) {
        let self_len = self.len;
        let new_len = self.len + right.len;
        assert!(new_len <= self.keys.len());
        for i in self.len .. new_len {
            self.keys[i] = mem::replace(&mut right.keys[i - self_len], Default::default());
        }
    }
    pub fn dump(&self) {
        debug!("Dumping {:?}, keys {}", self.id, self.len);
        for i in 0..NUM_KEYS {
            println!("{}\t- {:?}", i, self.keys[i]);
        }
    }
}

pub fn rearrange_empty_extnode(node: &ExtNode, bz: &CacheBufferZone) -> Id {
    let prev = node.prev;
    let next = node.next;
    if !prev.is_unit_id() {
        let mut prev_node = bz.get_for_mut(&prev);
        prev_node.next = next;
    }
    if !next.is_unit_id() {
        let mut next_node = bz.get_for_mut(&next);
        next_node.prev = prev;
    }
    return node.id;
}

#[derive(Clone)]
pub enum CacheGuardHolder {
    Read(ExtNodeCachedImmute),
    Write(ExtNodeCachedMut)
}

type NodeRcRefCell = Rc<RefCell<ExtNode>>;

pub type RcNodeRefData<'a> = OwningHandle<RcRef<RefCell<ExtNode>>, Ref<'a, ExtNode>>;
pub type RcNodeRefMut<'a> = OwningHandle<RcRef<RefCell<ExtNode>>, RefMut<'a, ExtNode>>;

pub enum RcNodeRef<'a> {
    Data(RcNodeRefData<'a>),
    Guard(CacheGuardHolder)
}

pub struct CacheBufferZone {
    mapper: Arc<ExtNodeCacheMap>,
    storage: Arc<AsyncClient>,
    guards: RefCell<BTreeMap<Id, CacheGuardHolder>>,
    data: RefCell<BTreeMap<Id, Option<NodeRcRefCell>>>
}

impl Deref for CacheGuardHolder {
    type Target = ExtNode;

    fn deref(&self) -> &'_ <Self as Deref>::Target {
        match self {
            &CacheGuardHolder::Read(ref g) => &*g,
            &CacheGuardHolder::Write(ref g) => &*g
        }
    }
}

impl <'a> Deref for RcNodeRef<'a> {
    type Target = ExtNode;

    fn deref(&self) -> &'_ <Self as Deref>::Target {
        match self {
            &RcNodeRef::Guard(ref g) => &*g,
            &RcNodeRef::Data(ref g) => &*g
        }
    }
}

impl CacheBufferZone {
    pub fn new(mapper: &Arc<ExtNodeCacheMap>, storage: &Arc<AsyncClient>) -> CacheBufferZone {
        CacheBufferZone {
            mapper: mapper.clone() ,
            storage: storage.clone(),
            guards: RefCell::new(BTreeMap::new()),
            data: RefCell::new(BTreeMap::new())
        }
    }

    pub fn get(&self, id: &Id) -> RcNodeRef {
        debug!("Getting cached fo readonly {:?}", id);
        {
            // read from data (from write)
            let data = self.data.borrow();
            match data.get(id) {
                Some(Some(ref data)) => {
                    let cell = data.clone();
                    let cell_ref = RcRef::new(cell);
                    let handle = OwningHandle::new(cell_ref);
                    return RcNodeRef::Data(handle);
                },
                Some(None) => panic!(), // deleted
                _ => {}
            }
        }
        {
            // read from guards
            let guard = self.guards.borrow();
            if let Some(holder) = guard.get(id) {
                return RcNodeRef::Guard(holder.clone());
            }
        }
        {
            debug!("Buffer zone inserting for readonly");
            let guard = self.get_ext_node_cached(id);
            let holder = CacheGuardHolder::Read(guard);
            let mut guards = self.guards.borrow_mut();
            guards.insert(*id, holder);
            debug!("Buffer zone now have data {}", guards.len());
        }
        return self.get(id);
    }

    pub fn get_for_mut(&self, id: &Id) -> RcNodeRefMut {
        debug!("Getting cached for mutation {:?}", id);
        {
            let data = self.data.borrow();
            match data.get(id) {
                Some(Some(ref extnode)) => {
                    let guards = self.guards.borrow();
                    if let CacheGuardHolder::Read(_) = guards.get(id).unwrap() {
                        panic!("Mutating readonly buffered cache");
                    }
                    let cell = extnode.clone();
                    let cell_ref = RcRef::new(cell);
                    let handle = OwningHandle::new_mut(cell_ref);
                    debug!("Got cached, len {}, cache data {}, cache guards {}", handle.len, data.len(), guards.len());
                    return handle
                },
                Some(None) => panic!(),
                _ => {}
            }
        }
        {
            debug!("Buffer zone inserting for mutation {:?}", id);
            let guard = self.get_mut_ext_node_cached(id);
            let mut data = self.data.borrow_mut();
            data.insert(*id, Some(Rc::new(RefCell::new((&*guard).clone()))));
            let holder = CacheGuardHolder::Write(guard);
            let mut guards = self.guards.borrow_mut();
            guards.insert(*id, holder);
            debug!("Buffer zone now have data {}, guards {}", data.len(), guards.len());
        }
        self.get_for_mut(id)
    }

    pub fn delete(&self, id: &Id) {
        let mut data = self.data.borrow_mut();
        data.insert(*id, None);
    }

    pub fn new_node(&self, node: ExtNode) {
        let mut mapper = self.mapper.lock();
        if mapper.get(&node.id).is_some() {
            panic!()
        } else {
            let node_id = node.id;
            let lock = RwLock::new(ExtNode::new(&node_id));
            let guard = CacheGuardHolder::Write(lock.write());
            let mut guards = self.guards.borrow_mut();
            let mut data = self.data.borrow_mut();
            debug!("new node in buffered cache: {:?}, was guards: {}, data: {}", node_id, guards.len(), data.len());
            mapper.insert(node_id, lock);
            guards.insert(node_id, guard);
            data.insert(node_id, Some(Rc::new(RefCell::new(node))));
        }
    }

    pub fn flush(&self) {
        let mut guards = self.guards.borrow_mut();
        let data = self.data.borrow();
        debug!("Flushing cache buffer, guards: {:?}, data: {:?}", guards.keys(), data.keys());
        for ((id, data),  (gid, mut holder)) in data.iter().zip(guards.iter_mut()) {
            assert_eq!(id, gid);
            if let Some(ref node_rc) = data {
                debug!("Flushing updating node: {:?}", id);
                if let &mut CacheGuardHolder::Write(ref mut guard) = holder {
                    let mut ext_node = (*(*node_rc).borrow()).clone();
                    debug!("flushing {:?} to cache with {} keys", ext_node.id, ext_node.len);
                    **guard = ext_node
                }
            } else {
                debug!("Flushing deleting node: {:?}", id);
                self.mapper.lock().remove(id);
                self.storage.remove_cell(*id).wait().unwrap();
            }
        }
    }

    pub fn get_guard(&self, id: &Id) -> Option<CacheGuardHolder> {
        if id.is_unit_id() {
            return None;
        }
        let mut guards = self.guards.borrow_mut();
        {
            let res = guards.get(id).map(|rg| rg.clone());
            if res.is_some() { return res; }
        }
        let guard = self.get_ext_node_cached(id);
        let holder = CacheGuardHolder::Read(guard);
        guards.insert(*id, holder.clone());
        return Some(holder)
    }

    pub fn get_mut_ext_node_cached(&self, id: &Id) -> ExtNodeCachedMut {
        let mut map = self.mapper.lock();
        return map.get_or_fetch(id).unwrap().write();
    }
    pub fn get_ext_node_cached(&self, id: &Id) -> ExtNodeCachedImmute {
        let mut map = self.mapper.lock();
        return map.get_or_fetch(id).unwrap().read();
    }
}

pub fn page_schema() -> Schema {
    Schema {
        id: *PAGE_SCHEMA_ID,
        name: String::from(PAGE_SCHEMA),
        key_field: None,
        str_key_field: None,
        is_dynamic: false,
        fields: Field::new(
            "*", 0, false, false,
            Some(vec![
                Field::new(NEXT_FIELD, type_id_of(Type::Id), false, false, None),
                Field::new(PREV_FIELD, type_id_of(Type::Id), false, false, None),
                Field::new(KEYS_FIELD, type_id_of(Type::U8), false, true, None)
            ])
        )
    }
}
<commit_msg>split bondary<commit_after>use utils::lru_cache::LRUCache;
use dovahkiin::types::custom_types::id::Id;
use dovahkiin::types::custom_types::map::Map;
use std::cell::RefCell;
use ram::cell::Cell;
use ram::types::*;
use std::cell::Ref;
use std::cell::RefMut;
use index::btree::*;
use bifrost::utils::async_locks::{RwLock, RwLockWriteGuard, RwLockReadGuard, Mutex};
use std::ops::Deref;
use std::ops::DerefMut;
use core::borrow::BorrowMut;
use dovahkiin::types::value::ToValue;
use itertools::Itertools;
use std::collections::BTreeMap;
use std::mem;
use std::rc::Rc;
use owning_ref::{RcRef, OwningHandle, OwningRef};
use ram::schema::{Schema, Field};
use dovahkiin::types::type_id_of;
use std::sync::Arc;
use client::AsyncClient;
use futures::Future;

pub type ExtNodeCacheMap = Mutex<LRUCache<Id, RwLock<ExtNode>>>;
pub type ExtNodeCachedMut = RwLockWriteGuard<ExtNode>;
pub type ExtNodeCachedImmute = RwLockReadGuard<ExtNode>;

const PAGE_SCHEMA: &'static str = "NEB_BTREE_PAGE";
const KEYS_FIELD: &'static str = "keys";
const NEXT_FIELD: &'static str = "next";
const PREV_FIELD: &'static str = "prev";

lazy_static! {
    static ref KEYS_KEY_HASH : u64 = key_hash(KEYS_FIELD);
    static ref NEXT_PAGE_KEY_HASH : u64 = key_hash(NEXT_FIELD);
    static ref PREV_PAGE_KEY_HASH : u64 = key_hash(PREV_FIELD);
    static ref PAGE_SCHEMA_ID: u32 = key_hash(PAGE_SCHEMA) as u32;
}

#[derive(Clone)]
pub struct ExtNode {
    pub id: Id,
    pub keys: EntryKeySlice,
    pub next: Id,
    pub prev: Id,
    pub len: usize,
    pub version: u64,
    pub removed: bool,
}

pub struct ExtNodeSplit {
    pub node_2: ExtNode,
    pub keys_1_len: usize
}

impl ExtNode {
    pub fn new(id: &Id) -> ExtNode {
        ExtNode {
            id: *id,
            keys: EntryKeySlice::init(),
            next: Id::unit_id(),
            prev: Id::unit_id(),
            len: 0,
            version: 0,
            removed: false
        }
    }
    pub fn from_cell(cell: Cell) -> Self {
        let keys = &cell.data[*KEYS_KEY_HASH];
        let keys_len = keys.len().unwrap();
        let mut key_slice = EntryKeySlice::init();
        let mut key_count = 0;
        let next = cell.data[*NEXT_PAGE_KEY_HASH].Id().unwrap();
        let prev = cell.data[*PREV_PAGE_KEY_HASH].Id().unwrap();
        for (i, key_val) in keys.iter_value().unwrap().enumerate() {
            let key = if let Value::PrimArray(PrimitiveArray::U8(ref array)) = key_val {
                EntryKey::from_slice(array.as_slice())
            } else { panic!("invalid entry") };
            key_slice[i] = key;
            key_count += 1;
        }
        ExtNode {
            id: cell.id(),
            keys: key_slice,
            next: *next,
            prev: *prev,
            len: key_count,
            version: cell.header.version,
            removed: false
        }
    }
    pub fn to_cell(&self) -> Cell {
        let mut value = Value::Map(Map::new());
        value[*NEXT_PAGE_KEY_HASH] = Value::Id(self.next);
        value[*KEYS_KEY_HASH] = self
            .keys[..self.len]
            .iter()
            .map(|key| {
                key.as_slice().to_vec().value()
            })
            .collect_vec()
            .value();
        Cell::new_with_id(*PAGE_SCHEMA_ID, &self.id, value)
    }
    pub fn remove(&mut self, pos: usize) {
        let cached_len = self.len;
        self.keys.remove_at(pos, cached_len);
        self.len -= 1;
    }
    pub fn insert(
        &mut self,
        key: EntryKey,
        pos: usize,
        tree: &BPlusTree,
        bz: &CacheBufferZone)
        -> Option<(Node, Option<EntryKey>)>
    {
        let mut cached = self;
        let cached_len = cached.len;
        if cached_len >= NUM_KEYS {
            // need to split
            debug!("insert to external with split");
            cached.dump();
            let pivot = cached_len / 2;
            let split = {
                let cached_next = *&cached.next;
                let cached_id = *&cached.id;
                let new_page_id = tree.new_page_id();
                cached.next = new_page_id;
                let mut keys_1 = &mut cached.keys;
                let mut keys_2 = keys_1.split_at_pivot(pivot, cached_len);
                let mut keys_1_len = pivot;
                let mut keys_2_len = cached_len - pivot;
                insert_into_split(
                    key,
                    keys_1, &mut keys_2,
                    &mut keys_1_len, &mut keys_2_len,
                    pos, pivot);
                ExtNodeSplit {
                    keys_1_len,
                    node_2: ExtNode {
                        id: new_page_id,
                        keys: keys_2,
                        next: cached_next,
                        prev: cached_id,
                        len: keys_2_len,
                        version: 0,
                        removed: false
                    }
                }
            };
            cached.next = split.node_2.id;
            cached.len = split.keys_1_len;
            let node_2_id = split.node_2.id;
            let node_2 = Node::External(box node_2_id);
            debug!("Split to left len {}, right len {}", cached.len, split.node_2.len);
            cached.dump();
            split.node_2.dump();
            bz.new_node(split.node_2);
            return Some((node_2, None));

        } else {
            debug!("insert to external without split at {}, key {:?}", pos, key);
            cached.keys.insert_at(key, pos, cached_len);
            cached.len += 1;
            return None;
        }
    }
    pub fn merge_with(&mut self, right: &mut Self) {
        let self_len = self.len;
        let new_len = self.len + right.len;
        assert!(new_len <= self.keys.len());
        for i in self.len .. new_len {
            self.keys[i] = mem::replace(&mut right.keys[i - self_len], Default::default());
        }
    }
    pub fn dump(&self) {
        debug!("Dumping {:?}, keys {}", self.id, self.len);
        for i in 0..NUM_KEYS {
            println!("{}\t- {:?}", i, self.keys[i]);
        }
    }
}

pub fn rearrange_empty_extnode(node: &ExtNode, bz: &CacheBufferZone) -> Id {
    let prev = node.prev;
    let next = node.next;
    if !prev.is_unit_id() {
        let mut prev_node = bz.get_for_mut(&prev);
        prev_node.next = next;
    }
    if !next.is_unit_id() {
        let mut next_node = bz.get_for_mut(&next);
        next_node.prev = prev;
    }
    return node.id;
}

#[derive(Clone)]
pub enum CacheGuardHolder {
    Read(ExtNodeCachedImmute),
    Write(ExtNodeCachedMut)
}

type NodeRcRefCell = Rc<RefCell<ExtNode>>;

pub type RcNodeRefData<'a> = OwningHandle<RcRef<RefCell<ExtNode>>, Ref<'a, ExtNode>>;
pub type RcNodeRefMut<'a> = OwningHandle<RcRef<RefCell<ExtNode>>, RefMut<'a, ExtNode>>;

pub enum RcNodeRef<'a> {
    Data(RcNodeRefData<'a>),
    Guard(CacheGuardHolder)
}

pub struct CacheBufferZone {
    mapper: Arc<ExtNodeCacheMap>,
    storage: Arc<AsyncClient>,
    guards: RefCell<BTreeMap<Id, CacheGuardHolder>>,
    data: RefCell<BTreeMap<Id, Option<NodeRcRefCell>>>
}

impl Deref for CacheGuardHolder {
    type Target = ExtNode;

    fn deref(&self) -> &'_ <Self as Deref>::Target {
        match self {
            &CacheGuardHolder::Read(ref g) => &*g,
            &CacheGuardHolder::Write(ref g) => &*g
        }
    }
}

impl <'a> Deref for RcNodeRef<'a> {
    type Target = ExtNode;

    fn deref(&self) -> &'_ <Self as Deref>::Target {
        match self {
            &RcNodeRef::Guard(ref g) => &*g,
            &RcNodeRef::Data(ref g) => &*g
        }
    }
}

impl CacheBufferZone {
    pub fn new(mapper: &Arc<ExtNodeCacheMap>, storage: &Arc<AsyncClient>) -> CacheBufferZone {
        CacheBufferZone {
            mapper: mapper.clone() ,
            storage: storage.clone(),
            guards: RefCell::new(BTreeMap::new()),
            data: RefCell::new(BTreeMap::new())
        }
    }

    pub fn get(&self, id: &Id) -> RcNodeRef {
        debug!("Getting cached fo readonly {:?}", id);
        {
            // read from data (from write)
            let data = self.data.borrow();
            match data.get(id) {
                Some(Some(ref data)) => {
                    let cell = data.clone();
                    let cell_ref = RcRef::new(cell);
                    let handle = OwningHandle::new(cell_ref);
                    return RcNodeRef::Data(handle);
                },
                Some(None) => panic!(), // deleted
                _ => {}
            }
        }
        {
            // read from guards
            let guard = self.guards.borrow();
            if let Some(holder) = guard.get(id) {
                return RcNodeRef::Guard(holder.clone());
            }
        }
        {
            debug!("Buffer zone inserting for readonly");
            let guard = self.get_ext_node_cached(id);
            let holder = CacheGuardHolder::Read(guard);
            let mut guards = self.guards.borrow_mut();
            guards.insert(*id, holder);
            debug!("Buffer zone now have data {}", guards.len());
        }
        return self.get(id);
    }

    pub fn get_for_mut(&self, id: &Id) -> RcNodeRefMut {
        debug!("Getting cached for mutation {:?}", id);
        {
            let data = self.data.borrow();
            match data.get(id) {
                Some(Some(ref extnode)) => {
                    let guards = self.guards.borrow();
                    if let CacheGuardHolder::Read(_) = guards.get(id).unwrap() {
                        panic!("Mutating readonly buffered cache");
                    }
                    let cell = extnode.clone();
                    let cell_ref = RcRef::new(cell);
                    let handle = OwningHandle::new_mut(cell_ref);
                    debug!("Got cached, len {}, cache data {}, cache guards {}", handle.len, data.len(), guards.len());
                    return handle
                },
                Some(None) => panic!(),
                _ => {}
            }
        }
        {
            debug!("Buffer zone inserting for mutation {:?}", id);
            let guard = self.get_mut_ext_node_cached(id);
            let mut data = self.data.borrow_mut();
            data.insert(*id, Some(Rc::new(RefCell::new((&*guard).clone()))));
            let holder = CacheGuardHolder::Write(guard);
            let mut guards = self.guards.borrow_mut();
            guards.insert(*id, holder);
            debug!("Buffer zone now have data {}, guards {}", data.len(), guards.len());
        }
        self.get_for_mut(id)
    }

    pub fn delete(&self, id: &Id) {
        let mut data = self.data.borrow_mut();
        data.insert(*id, None);
    }

    pub fn new_node(&self, node: ExtNode) {
        let mut mapper = self.mapper.lock();
        if mapper.get(&node.id).is_some() {
            panic!()
        } else {
            let node_id = node.id;
            let lock = RwLock::new(ExtNode::new(&node_id));
            let guard = CacheGuardHolder::Write(lock.write());
            let mut guards = self.guards.borrow_mut();
            let mut data = self.data.borrow_mut();
            debug!("new node in buffered cache: {:?}, was guards: {}, data: {}", node_id, guards.len(), data.len());
            mapper.insert(node_id, lock);
            guards.insert(node_id, guard);
            data.insert(node_id, Some(Rc::new(RefCell::new(node))));
        }
    }

    pub fn flush(&self) {
        let mut guards = self.guards.borrow_mut();
        let data = self.data.borrow();
        debug!("Flushing cache buffer, guards: {:?}, data: {:?}", guards.keys(), data.keys());
        for ((id, data),  (gid, mut holder)) in data.iter().zip(guards.iter_mut()) {
            assert_eq!(id, gid);
            if let Some(ref node_rc) = data {
                debug!("Flushing updating node: {:?}", id);
                if let &mut CacheGuardHolder::Write(ref mut guard) = holder {
                    let mut ext_node = (*(*node_rc).borrow()).clone();
                    debug!("flushing {:?} to cache with {} keys", ext_node.id, ext_node.len);
                    **guard = ext_node
                }
            } else {
                debug!("Flushing deleting node: {:?}", id);
                self.mapper.lock().remove(id);
                self.storage.remove_cell(*id).wait().unwrap();
            }
        }
    }

    pub fn get_guard(&self, id: &Id) -> Option<CacheGuardHolder> {
        if id.is_unit_id() {
            return None;
        }
        let mut guards = self.guards.borrow_mut();
        {
            let res = guards.get(id).map(|rg| rg.clone());
            if res.is_some() { return res; }
        }
        let guard = self.get_ext_node_cached(id);
        let holder = CacheGuardHolder::Read(guard);
        guards.insert(*id, holder.clone());
        return Some(holder)
    }

    pub fn get_mut_ext_node_cached(&self, id: &Id) -> ExtNodeCachedMut {
        let mut map = self.mapper.lock();
        return map.get_or_fetch(id).unwrap().write();
    }
    pub fn get_ext_node_cached(&self, id: &Id) -> ExtNodeCachedImmute {
        let mut map = self.mapper.lock();
        return map.get_or_fetch(id).unwrap().read();
    }
}

pub fn page_schema() -> Schema {
    Schema {
        id: *PAGE_SCHEMA_ID,
        name: String::from(PAGE_SCHEMA),
        key_field: None,
        str_key_field: None,
        is_dynamic: false,
        fields: Field::new(
            "*", 0, false, false,
            Some(vec![
                Field::new(NEXT_FIELD, type_id_of(Type::Id), false, false, None),
                Field::new(PREV_FIELD, type_id_of(Type::Id), false, false, None),
                Field::new(KEYS_FIELD, type_id_of(Type::U8), false, true, None)
            ])
        )
    }
}
<|endoftext|>


<commit_before>use schema::Term;
use std::sync::{Arc, RwLock};
use std::collections::HashMap;
use std::sync::atomic::{AtomicUsize, Ordering};

pub struct SuscribeHandle {
    client_id: usize,
    clients: Arc<RwLock<HashMap<usize, u64>>>,
}

impl Drop for SuscribeHandle {
    fn drop(&mut self) {
        self.clients
            .write()
            .unwrap()
            .remove(&self.client_id);
    }
}

struct ClientSuscriptionRegister {
    clients: Arc<RwLock<HashMap<usize, u64>>>,
    client_id_autoinc: AtomicUsize,
}

impl Default for ClientSuscriptionRegister {
    fn default() -> ClientSuscriptionRegister {
        ClientSuscriptionRegister {
            clients: Arc::new(RwLock::new(HashMap::new())),
            client_id_autoinc: AtomicUsize::new(0),
        }
    }
}

impl ClientSuscriptionRegister {
    fn acquire_client_id(&mut self) -> usize {
        self.client_id_autoinc.fetch_add(1, Ordering::SeqCst)
    }

    fn suscribe(&mut self, opstamp: u64) -> SuscribeHandle {
        let client_id = self.acquire_client_id();
        self.clients
            .write()
            .unwrap()
            .insert(client_id, opstamp);
        SuscribeHandle {
            client_id: client_id,
            clients: self.clients.clone(),
        }
    }

}

pub struct DeleteQueue {
    operations: Vec<DeleteOperation>,
    client_subscription_register: ClientSuscriptionRegister,
}

impl DeleteQueue {
    pub fn push(&mut self, opstamp: u64, term: Term) {
        self.operations.push(DeleteOperation {
            opstamp: opstamp,
            term: term
        });
    }

    pub fn suscribe(&mut self, opstamp: u64) -> SuscribeHandle {
        self.client_subscription_register.suscribe(opstamp)
    }
}

impl Default for DeleteQueue {
    fn default() -> DeleteQueue {
        DeleteQueue {
            operations: Vec::new(),
            client_subscription_register: ClientSuscriptionRegister::default(),
        }
    }
}

struct DeleteOperation {
    opstamp: u64,
    term: Term,
}
<commit_msg>issue/43 Change the delete queue datastruct for something cleaner/functional<commit_after>use schema::Term;
use std::sync::{Arc, RwLock};
use std::collections::HashMap;
use std::sync::atomic::{AtomicUsize, Ordering};

const BLOCK_SIZE: usize = 128;

struct DeleteOperation {
    pub opstamp: u64,
    pub term: Term,
}

struct Block {
    operations: Vec<DeleteOperation>,
    next: Option<SharedBlock>,
}

impl Default for Block {
    fn default() -> Block {
        Block {
            operations: Vec::with_capacity(BLOCK_SIZE),
            next: None
        }
    }
}

#[derive(Clone)]
struct SharedBlock {
    inner: Arc<RwLock<Block>>,
}

impl SharedBlock {
    // Happens a new element to the block and return
    // what the new head is.
    fn enqueue(&self, delete_operation: DeleteOperation) -> Option<SharedBlock> {
        let mut writable_block = self.inner.write().expect("Panicked while enqueueing in the delete queue.");
        if writable_block.operations.len() >= BLOCK_SIZE {
            let next_block = SharedBlock::default();
            next_block.enqueue(delete_operation);
            writable_block.next = Some(next_block.clone());
            Some(next_block)
        }
        else {
            writable_block.operations.push(delete_operation);
            None
        }
    }

    fn cursor(&self,) -> DeleteQueueCursor {
        let len = self.inner
            .read()
            .expect("Panicked while reading a block in the delete queue.")
            .operations
            .len();
        DeleteQueueCursor {
            block: self.clone(),
            pos: len,
        }
    }
}

impl Default for SharedBlock {
    fn default() -> SharedBlock {
        SharedBlock {
            inner: Arc::default()
        }
    }
}

impl Default for DeleteQueue {
    fn default() -> DeleteQueue {
        DeleteQueue {
            head: SharedBlock::default(),
        }
    }
}

pub struct DeleteQueueCursor {
    block: SharedBlock,
    pos: usize,
}

// ----------------------------------------

pub struct DeleteQueue {
    head: SharedBlock,
}

impl DeleteQueue {

    pub fn cursor(&self) -> DeleteQueueCursor {
        self.head.cursor()
    }

    pub fn push(&mut self, opstamp: u64, term: Term) {
        let delete_operation = DeleteOperation {
            opstamp: opstamp,
            term: term,
        };
        if let Some(new_head) = self.head.enqueue(delete_operation) {
            self.head = new_head;
        }
    }
}
<|endoftext|>


<commit_before>use types::*;
use instruction::{Instruction,Pattern, Coding, Definition, OperandKind};
use execution::Operation;

pub struct CodewordMatcher {
    code: Codeword,
    mask: Codeword,
}

/// Matches a codeword
impl CodewordMatcher {
    pub fn new(pattern: Pattern) -> CodewordMatcher {
        let mut code: Codeword = 0;
        let mut mask: Codeword = 0;
        for coding in &pattern {
            code <<= 4;
            mask <<= 4;
            if let Coding::C(n) = *coding {
                code |= n as Codeword;
                mask |= 0xF;
            };
        }
        CodewordMatcher {
            code: code,
            mask: mask,
        }
    }
    /// Returns true if a given codeword matches this definition.
    pub fn is_match(&self, codeword: Codeword) -> bool {
        (codeword & self.mask) == (self.code & self.mask)
    }

}

/// Matches an instruction
pub struct InstructionMatcher {
    operation: Operation,
    dest_kind: OperandKind,
    src_kind: OperandKind,
    aux_kind: OperandKind,
}

impl InstructionMatcher {
    pub fn new(definition: &Definition) -> InstructionMatcher {
        InstructionMatcher {
            operation: definition.operation,
            dest_kind: definition.dest_kind,
            src_kind: definition.src_kind,
            aux_kind: definition.aux_kind,
        }
    }

    pub fn is_match(&self, inst: &Instruction) -> bool {
        self.operation == inst.operation() &&
        self.dest_kind == inst.dest().kind() &&
        self.src_kind == inst.src().kind() &&
        self.aux_kind == inst.aux().kind()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use instruction::{Definition, Instruction, Operand, OperandKind};
    use instruction::Coding::*;
    use execution::Operation;

    #[test]
    fn test_code_match() {
        let cm = CodewordMatcher::new([C(0xA), C(0x5), D, C(0x0)]);
        assert!(cm.is_match(0xA500));
        assert!(cm.is_match(0xA5E0));
        assert!(!cm.is_match(0xB580));

        let cm = CodewordMatcher::new([D, S, C(0xA), A]);
        assert!(!cm.is_match(0xA500));
        assert!(cm.is_match(0xA5A7));
        assert!(cm.is_match(0xB5A0));

    }

    #[test]
    fn test_inst_match() {
        let definition = Definition {
            operation: Operation::OpAdd,
            dest_kind: OperandKind::Register,
            src_kind: OperandKind::Register,
            aux_kind: OperandKind::Unused,
            pattern: [C(0x2), D, S, C(0)],
        };

        let im = InstructionMatcher::new(&definition);

        let d2 = Definition {
            operation: Operation::OpSub,
            dest_kind: OperandKind::Register,
            src_kind: OperandKind::Register,
            aux_kind: OperandKind::Unused,
            pattern: [C(0x2), D, S, C(0)],
        };

        let d3 = Definition {
            operation: Operation::OpAdd,
            dest_kind: OperandKind::Register,
            src_kind: OperandKind::Register,
            aux_kind: OperandKind::Unused,
            pattern: [C(0x2), D, S, C(0xF)],
        };

        let inst = Instruction::new(&definition, 0x2740);
        assert!(im.is_match(&inst));
        let inst = Instruction::new(&definition, 0x2380);
        assert!(im.is_match(&inst));

        let inst = Instruction::new(&definition, 0x20D0);
        assert!(im.is_match(&inst));
        let inst = Instruction::new(&d2, 0x2340);
        assert!(!im.is_match(&inst));
        // same operation, src and aux
        let inst = Instruction::new(&d3, 0x2340);
        assert!(im.is_match(&inst));

    }

}
<commit_msg>code and instruction matching complete with tests<commit_after>use types::*;
use instruction::{Instruction,Pattern, Coding, Definition, OperandKind};
use execution::Operation;

pub struct CodewordMatcher {
    code: Codeword,
    mask: Codeword,
}

/// Matches a codeword
impl CodewordMatcher {
    pub fn new(pattern: Pattern) -> CodewordMatcher {
        let mut code: Codeword = 0;
        let mut mask: Codeword = 0;
        for coding in &pattern {
            code <<= 4;
            mask <<= 4;
            if let Coding::C(n) = *coding {
                code |= n as Codeword;
                mask |= 0xF;
            };
        }
        CodewordMatcher {
            code: code,
            mask: mask,
        }
    }
    /// Returns true if a given codeword matches this definition.
    pub fn is_match(&self, codeword: Codeword) -> bool {
        (codeword & self.mask) == (self.code & self.mask)
    }

}

/// Matches an instruction
pub struct InstructionMatcher {
    operation: Operation,
    dest_kind: OperandKind,
    src_kind: OperandKind,
    aux_kind: OperandKind,
    pattern: Pattern,
}

impl InstructionMatcher {
    pub fn new(definition: &Definition) -> InstructionMatcher {
        InstructionMatcher {
            operation: definition.operation,
            dest_kind: definition.dest_kind,
            src_kind: definition.src_kind,
            aux_kind: definition.aux_kind,
            pattern: definition.pattern,
        }
    }

    pub fn is_match(&self, inst: &Instruction) -> bool {
        self.operation == inst.operation() &&
        self.dest_kind == inst.dest().kind() &&
        self.src_kind == inst.src().kind() &&
        self.aux_kind == inst.aux().kind()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use instruction::{Definition, Instruction, Operand, OperandKind};
    use instruction::Coding::*;
    use execution::Operation;

    #[test]
    fn test_code_match() {
        let cm = CodewordMatcher::new([C(0xA), C(0x5), D, C(0x0)]);
        assert!(cm.is_match(0xA500));
        assert!(cm.is_match(0xA5E0));
        assert!(!cm.is_match(0xB580));

        let cm = CodewordMatcher::new([D, S, C(0xA), A]);
        assert!(!cm.is_match(0xA500));
        assert!(cm.is_match(0xA5A7));
        assert!(cm.is_match(0xB5A0));

    }

    #[test]
    fn test_inst_match() {
        let definition = Definition {
            operation: Operation::OpAdd,
            dest_kind: OperandKind::Register,
            src_kind: OperandKind::Register,
            aux_kind: OperandKind::Unused,
            pattern: [C(0x2), D, S, C(0)],
        };

        let im = InstructionMatcher::new(&definition);

        let d2 = Definition {
            operation: Operation::OpSub,
            dest_kind: OperandKind::Register,
            src_kind: OperandKind::Register,
            aux_kind: OperandKind::Unused,
            pattern: [C(0x2), D, S, C(0)],
        };

        let d3 = Definition {
            operation: Operation::OpAdd,
            dest_kind: OperandKind::Register,
            src_kind: OperandKind::Register,
            aux_kind: OperandKind::Unused,
            pattern: [C(0x2), D, S, C(0xF)],
        };

        let inst = Instruction::new(&definition, 0x2740);
        assert!( im.is_match(&inst) );
        let inst = Instruction::new(&definition, 0x2380);
        assert!( im.is_match(&inst) );
        let inst = Instruction::new(&definition, 0x20D0);
        assert!( im.is_match(&inst) );
        let inst = Instruction::new(&d2, 0x2340);
        assert!( ! im.is_match(&inst) );
        let inst = Instruction::new(&d3, 0x2340);
        //matches because the pattern and codeword are not taken into account.
        assert!( im.is_match(&inst) );

    }

}
<|endoftext|>


<commit_before>use super::super::commands::CommandResult;
use super::super::{LayoutTree, TreeError};
use super::super::core::Direction;
use super::super::core::container::{Container, ContainerType, Handle, Layout};

use petgraph::graph::NodeIndex;
use rustwlc::WlcView;
use uuid::Uuid;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum FocusError {
    /// Reached a container where we can keep climbing the tree no longer.
    ///
    /// Usually this is a workspace, because it doesn't make sense to move a
    /// container out of a workspace
    ReachedLimit(NodeIndex),
    /// Tried to focus on a container that was not a view.
    NotAView(Uuid),
    /// Tried to focus on a container (first one),
    /// but that container was superseded by a fullscreen container (second one)
    BlockedByFullscreen(Uuid, Uuid)
}

impl LayoutTree {
    /// Focuses on the container by the uuid, if it points to a View.
    /// Otherwise, an error is returned.
    pub fn focus_on(&mut self, uuid: Uuid) -> CommandResult {
        let container = try!(self.lookup(uuid));
        match *container {
            Container::View { handle, .. } => {
                handle.focus();
                Ok(())
            },
            _ => Err(TreeError::Focus(FocusError::NotAView(uuid)))
        }
    }
    /// Focus on the container relative to the active container.
    ///
    /// If Horizontal, left and right will move within siblings.
    /// If Vertical, up and down will move within siblings.
    /// Other wise, it moves to the next sibling of the parent container.
    ///
    /// If the edge of the children is hit, it does not wrap around,
    /// but moves between ancestor siblings.
    pub fn move_focus(&mut self, direction: Direction) -> CommandResult {
        if let Some(prev_active_ix) = self.active_container {
            let new_active_ix = self.move_focus_recurse(prev_active_ix, direction)
                .unwrap_or(prev_active_ix);
            try!(self.set_active_node(new_active_ix));
            match self.tree[self.active_container.unwrap()] {
                Container::View { ref handle, .. } => handle.focus(),
                _ => warn!("move_focus returned a non-view, cannot focus")
            }
        } else {
            warn!("Cannot move active focus when not there is no active container");
        }
        self.validate();
        Ok(())
    }

    pub fn move_focus_recurse(&mut self, node_ix: NodeIndex, direction: Direction) -> Result<NodeIndex, TreeError> {
        match self.tree[node_ix].get_type() {
            ContainerType::View | ContainerType::Container => { /* continue */ },
            _ => return Err(TreeError::UuidWrongType(self.tree[node_ix].get_id(),
                                                     vec!(ContainerType::View, ContainerType::Container)))
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Active ix had no parent");
        match self.tree[parent_ix] {
            Container::Container { layout, .. } => {
                match (layout, direction) {
                    (Layout::Horizontal, Direction::Left) |
                    (Layout::Horizontal, Direction::Right) |
                    (Layout::Vertical, Direction::Up) |
                    (Layout::Vertical, Direction::Down) => {
                        let siblings = self.tree.children_of(parent_ix);
                        let cur_index = siblings.iter().position(|node| {
                            *node == node_ix
                        }).expect("Could not find self in parent");
                        let maybe_new_index = match direction {
                            Direction::Right | Direction::Down => {
                                cur_index.checked_add(1)
                            }
                            Direction::Left  | Direction::Up => {
                                cur_index.checked_sub(1)
                            }
                        };
                        if maybe_new_index.is_some() &&
                            maybe_new_index.unwrap() < siblings.len() {
                                // There is a sibling to move to.
                                let new_index = maybe_new_index.unwrap();
                                let new_active_ix = siblings[new_index];
                                match self.tree[new_active_ix].get_type() {
                                    ContainerType::Container => {
                                        let path_ix = self.tree.follow_path(new_active_ix);
                                        // If the path wasn't complete, find the first view and focus on that
                                        let node_ix = try!(self.tree.descendant_of_type(path_ix, ContainerType::View)
                                                           .map_err(|err| TreeError::PetGraph(err)));
                                        let parent_ix = try!(self.tree.parent_of(node_ix)
                                                             .map_err(|err| TreeError::PetGraph(err)));
                                        match self.tree[node_ix].get_type() {
                                            ContainerType::View | ContainerType::Container => {},
                                            _ => panic!("Following path did not lead to a container or a view!")
                                        }
                                        trace!("Moving to different view {:?} in container {:?}",
                                                self.tree[node_ix], self.tree[parent_ix]);
                                        return Ok(node_ix);
                                    },
                                    ContainerType::View => {
                                        trace!("Moving to other view {:?}", self.tree[new_active_ix]);
                                        return Ok(new_active_ix)
                                    },
                                    _ => unreachable!()
                                };
                            }
                    },
                    _ => { /* We are moving out of siblings, recurse */ }
                }
            }
            Container::Workspace { .. } => {
                return Err(TreeError::Focus(FocusError::ReachedLimit(parent_ix)));
            }
            _ => unreachable!()
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Node had no parent");
        return self.move_focus_recurse(parent_ix, direction);
    }

    /// Updates the current active container to be the next container or view
    /// to focus on after the previous view/container was moved/removed.
    ///
    /// A new view will tried to be set, starting with the children of the
    /// parent node. If a view cannot be found there, it starts climbing the
    /// tree until either a view is found or the workspace is (in which case
    /// it set the active container to the root container of the workspace)
    pub fn focus_on_next_container(&mut self, mut parent_ix: NodeIndex) {
        let last_ix;
        {
            let path = self.tree.active_path();
            last_ix = path[path.len() - 1].0;
        }
        match self.tree[last_ix] {
            Container::View { handle, .. } => {
                handle.focus();
                self.active_container = Some(last_ix);
                return
            },
            Container::Container { .. } => {
                parent_ix = last_ix;
            },
            _ => {}
        }
        while self.tree.node_type(parent_ix)
            .expect("Node not part of the tree") != ContainerType::Workspace {
                if let Ok(view_ix) = self.tree.descendant_of_type(parent_ix,
                                                                  ContainerType::View) {
                match self.tree[view_ix]
                                    .get_handle().expect("view had no handle") {
                    Handle::View(view) => view.focus(),
                    _ => panic!("View had an output handle")
                }
                trace!("Active container set to view at {:?}", view_ix);
                let id = self.tree[view_ix].get_id();
                self.set_active_container(id)
                    .expect("Could not set active container");
                return;
            }
            parent_ix = self.tree.ancestor_of_type(parent_ix,
                                                    ContainerType::Container)
                .unwrap_or_else(|_| {
                    self.tree.ancestor_of_type(parent_ix, ContainerType::Workspace)
                        .expect("Container was not part of a workspace")
                });
        }
        // If this is reached, parent is workspace
        let container_ix = self.tree.children_of(parent_ix)[0];
        let root_c_children = self.tree.grounded_children(container_ix);
        if root_c_children.len() > 0 {
            // Only searches first child of root container, can't be floating view.
            let new_active_ix = self.tree.descendant_of_type(root_c_children[0],
                                                                ContainerType::View)
                .unwrap_or(root_c_children[0]);
            let id = self.tree[new_active_ix].get_id();
            self.set_active_container(id)
                .expect("Could not set active container");
            match self.tree[new_active_ix] {
                Container::View { ref handle, .. } => {
                    info!("Focusing on {:?}", handle);
                    handle.focus();
                },
                Container::Container { .. } => {
                    info!("No view found, focusing on nothing in workspace {:?}", parent_ix);
                    WlcView::root().focus();
                }
                _ => unreachable!()
            };
            return;
        } else {
            let floating_children = self.tree.floating_children(container_ix);
            for child_ix in floating_children {
                if let Ok(view_ix) = self.tree.descendant_of_type(child_ix,
                                                                    ContainerType::View) {
                    match self.tree[view_ix] {
                        Container::View { handle, id, .. } => {
                            info!("Floating view found, focusing on {:#?}", handle);
                            handle.focus();
                            self.set_active_container(id)
                                .expect("Could not set active container");
                            return;
                        },
                        _ => unreachable!()
                    };
                }
            }
        }
        trace!("Active container set to container {:?}", container_ix);
        let id = self.tree[container_ix].get_id();
        self.set_active_container(id)
            .expect("Could not set active container");

        // Update focus to new container
        self.get_active_container().map(|con| match *con {
            Container::View { ref handle, .. } => handle.focus(),
            Container::Container { .. } => WlcView::root().focus(),
            _ => panic!("Active container not view or container!")
        });
    }

    /// If the currently focused view is floating, then the non-floating at the end of
    /// the path becomes the focused view. Otherwise, the first floating view becomes
    /// the focused view.
    ///
    /// If there is no currently focused view, does nothing.
    pub fn toggle_floating_focus(&mut self) -> CommandResult {
        let active_ix = try!(self.active_container.ok_or(TreeError::NoActiveContainer));
        if self.tree[active_ix].floating() {
            let root_ix = self.tree.root_ix();
            let new_ix = self.tree.follow_path(root_ix);
            match self.tree[new_ix].get_type() {
                ContainerType::View | ContainerType::Container  => {
                    try!(self.set_active_node(new_ix));
                    Ok(())
                },
                type_ => {
                    error!("Path lead to the wrong container, {:#?}\n{:#?}\n{:#?}",
                           active_ix, type_, self);
                    panic!("toggle_floating_focused: bad path");
                }
            }
        } else {
            // Current view is not floating, gotta focus on floating view
            let root_c_ix = self.root_container_ix()
                .expect("No root container ancestor of active container");
            let floating_children = self.tree.floating_children(root_c_ix);
            if floating_children.len() > 0 {
                try!(self.set_active_node(floating_children[0]));
            }
            Ok(())
        }
    }

    /// Normalizes the geometry of a view to be the same size as it's siblings,
    /// based on the parent container's layout, at the 0 point of the parent container.
    /// Note this does not auto-tile, only modifies this one view.
    ///
    /// Useful if a container's children want to be evenly distributed, or a new view
    /// is being added.
    pub fn normalize_view(&mut self, view: WlcView) {
        if let Some(view_ix) = self.tree.descendant_with_handle(self.tree.root_ix(), &view) {
            self.normalize_container(view_ix);
        }
    }
}
<commit_msg>Fixed visibilty in focus<commit_after>use super::super::commands::CommandResult;
use super::super::{LayoutTree, TreeError};
use super::super::core::Direction;
use super::super::core::container::{Container, ContainerType, Handle, Layout};

use petgraph::graph::NodeIndex;
use rustwlc::WlcView;
use uuid::Uuid;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum FocusError {
    /// Reached a container where we can keep climbing the tree no longer.
    ///
    /// Usually this is a workspace, because it doesn't make sense to move a
    /// container out of a workspace
    ReachedLimit(NodeIndex),
    /// Tried to focus on a container that was not a view.
    NotAView(Uuid),
    /// Tried to focus on a container (first one),
    /// but that container was superseded by a fullscreen container (second one)
    BlockedByFullscreen(Uuid, Uuid)
}

impl LayoutTree {
    /// Focuses on the container by the uuid, if it points to a View.
    /// Otherwise, an error is returned.
    pub fn focus_on(&mut self, uuid: Uuid) -> CommandResult {
        let container = try!(self.lookup(uuid));
        match *container {
            Container::View { handle, .. } => {
                handle.focus();
                Ok(())
            },
            _ => Err(TreeError::Focus(FocusError::NotAView(uuid)))
        }
    }
    /// Focus on the container relative to the active container.
    ///
    /// If Horizontal, left and right will move within siblings.
    /// If Vertical, up and down will move within siblings.
    /// Other wise, it moves to the next sibling of the parent container.
    ///
    /// If the edge of the children is hit, it does not wrap around,
    /// but moves between ancestor siblings.
    pub fn move_focus(&mut self, direction: Direction) -> CommandResult {
        if let Some(prev_active_ix) = self.active_container {
            let new_active_ix = self.move_focus_recurse(prev_active_ix, direction)
                .unwrap_or(prev_active_ix);
            try!(self.set_active_node(new_active_ix));
            match self.tree[self.active_container.unwrap()] {
                Container::View { ref handle, .. } => handle.focus(),
                _ => warn!("move_focus returned a non-view, cannot focus")
            }
        } else {
            warn!("Cannot move active focus when not there is no active container");
        }
        self.validate();
        Ok(())
    }

    fn move_focus_recurse(&mut self, node_ix: NodeIndex, direction: Direction) -> Result<NodeIndex, TreeError> {
        match self.tree[node_ix].get_type() {
            ContainerType::View | ContainerType::Container => { /* continue */ },
            _ => return Err(TreeError::UuidWrongType(self.tree[node_ix].get_id(),
                                                     vec!(ContainerType::View, ContainerType::Container)))
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Active ix had no parent");
        match self.tree[parent_ix] {
            Container::Container { layout, .. } => {
                match (layout, direction) {
                    (Layout::Horizontal, Direction::Left) |
                    (Layout::Horizontal, Direction::Right) |
                    (Layout::Vertical, Direction::Up) |
                    (Layout::Vertical, Direction::Down) => {
                        let siblings = self.tree.children_of(parent_ix);
                        let cur_index = siblings.iter().position(|node| {
                            *node == node_ix
                        }).expect("Could not find self in parent");
                        let maybe_new_index = match direction {
                            Direction::Right | Direction::Down => {
                                cur_index.checked_add(1)
                            }
                            Direction::Left  | Direction::Up => {
                                cur_index.checked_sub(1)
                            }
                        };
                        if maybe_new_index.is_some() &&
                            maybe_new_index.unwrap() < siblings.len() {
                                // There is a sibling to move to.
                                let new_index = maybe_new_index.unwrap();
                                let new_active_ix = siblings[new_index];
                                match self.tree[new_active_ix].get_type() {
                                    ContainerType::Container => {
                                        let path_ix = self.tree.follow_path(new_active_ix);
                                        // If the path wasn't complete, find the first view and focus on that
                                        let node_ix = try!(self.tree.descendant_of_type(path_ix, ContainerType::View)
                                                           .map_err(|err| TreeError::PetGraph(err)));
                                        let parent_ix = try!(self.tree.parent_of(node_ix)
                                                             .map_err(|err| TreeError::PetGraph(err)));
                                        match self.tree[node_ix].get_type() {
                                            ContainerType::View | ContainerType::Container => {},
                                            _ => panic!("Following path did not lead to a container or a view!")
                                        }
                                        trace!("Moving to different view {:?} in container {:?}",
                                                self.tree[node_ix], self.tree[parent_ix]);
                                        return Ok(node_ix);
                                    },
                                    ContainerType::View => {
                                        trace!("Moving to other view {:?}", self.tree[new_active_ix]);
                                        return Ok(new_active_ix)
                                    },
                                    _ => unreachable!()
                                };
                            }
                    },
                    _ => { /* We are moving out of siblings, recurse */ }
                }
            }
            Container::Workspace { .. } => {
                return Err(TreeError::Focus(FocusError::ReachedLimit(parent_ix)));
            }
            _ => unreachable!()
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Node had no parent");
        return self.move_focus_recurse(parent_ix, direction);
    }

    /// Updates the current active container to be the next container or view
    /// to focus on after the previous view/container was moved/removed.
    ///
    /// A new view will tried to be set, starting with the children of the
    /// parent node. If a view cannot be found there, it starts climbing the
    /// tree until either a view is found or the workspace is (in which case
    /// it set the active container to the root container of the workspace)
    pub fn focus_on_next_container(&mut self, mut parent_ix: NodeIndex) {
        let last_ix;
        {
            let path = self.tree.active_path();
            last_ix = path[path.len() - 1].0;
        }
        match self.tree[last_ix] {
            Container::View { handle, .. } => {
                handle.focus();
                self.active_container = Some(last_ix);
                return
            },
            Container::Container { .. } => {
                parent_ix = last_ix;
            },
            _ => {}
        }
        while self.tree.node_type(parent_ix)
            .expect("Node not part of the tree") != ContainerType::Workspace {
                if let Ok(view_ix) = self.tree.descendant_of_type(parent_ix,
                                                                  ContainerType::View) {
                match self.tree[view_ix]
                                    .get_handle().expect("view had no handle") {
                    Handle::View(view) => view.focus(),
                    _ => panic!("View had an output handle")
                }
                trace!("Active container set to view at {:?}", view_ix);
                let id = self.tree[view_ix].get_id();
                self.set_active_container(id)
                    .expect("Could not set active container");
                return;
            }
            parent_ix = self.tree.ancestor_of_type(parent_ix,
                                                    ContainerType::Container)
                .unwrap_or_else(|_| {
                    self.tree.ancestor_of_type(parent_ix, ContainerType::Workspace)
                        .expect("Container was not part of a workspace")
                });
        }
        // If this is reached, parent is workspace
        let container_ix = self.tree.children_of(parent_ix)[0];
        let root_c_children = self.tree.grounded_children(container_ix);
        if root_c_children.len() > 0 {
            // Only searches first child of root container, can't be floating view.
            let new_active_ix = self.tree.descendant_of_type(root_c_children[0],
                                                                ContainerType::View)
                .unwrap_or(root_c_children[0]);
            let id = self.tree[new_active_ix].get_id();
            self.set_active_container(id)
                .expect("Could not set active container");
            match self.tree[new_active_ix] {
                Container::View { ref handle, .. } => {
                    info!("Focusing on {:?}", handle);
                    handle.focus();
                },
                Container::Container { .. } => {
                    info!("No view found, focusing on nothing in workspace {:?}", parent_ix);
                    WlcView::root().focus();
                }
                _ => unreachable!()
            };
            return;
        } else {
            let floating_children = self.tree.floating_children(container_ix);
            for child_ix in floating_children {
                if let Ok(view_ix) = self.tree.descendant_of_type(child_ix,
                                                                    ContainerType::View) {
                    match self.tree[view_ix] {
                        Container::View { handle, id, .. } => {
                            info!("Floating view found, focusing on {:#?}", handle);
                            handle.focus();
                            self.set_active_container(id)
                                .expect("Could not set active container");
                            return;
                        },
                        _ => unreachable!()
                    };
                }
            }
        }
        trace!("Active container set to container {:?}", container_ix);
        let id = self.tree[container_ix].get_id();
        self.set_active_container(id)
            .expect("Could not set active container");

        // Update focus to new container
        self.get_active_container().map(|con| match *con {
            Container::View { ref handle, .. } => handle.focus(),
            Container::Container { .. } => WlcView::root().focus(),
            _ => panic!("Active container not view or container!")
        });
    }

    /// If the currently focused view is floating, then the non-floating at the end of
    /// the path becomes the focused view. Otherwise, the first floating view becomes
    /// the focused view.
    ///
    /// If there is no currently focused view, does nothing.
    pub fn toggle_floating_focus(&mut self) -> CommandResult {
        let active_ix = try!(self.active_container.ok_or(TreeError::NoActiveContainer));
        if self.tree[active_ix].floating() {
            let root_ix = self.tree.root_ix();
            let new_ix = self.tree.follow_path(root_ix);
            match self.tree[new_ix].get_type() {
                ContainerType::View | ContainerType::Container  => {
                    try!(self.set_active_node(new_ix));
                    Ok(())
                },
                type_ => {
                    error!("Path lead to the wrong container, {:#?}\n{:#?}\n{:#?}",
                           active_ix, type_, self);
                    panic!("toggle_floating_focused: bad path");
                }
            }
        } else {
            // Current view is not floating, gotta focus on floating view
            let root_c_ix = self.root_container_ix()
                .expect("No root container ancestor of active container");
            let floating_children = self.tree.floating_children(root_c_ix);
            if floating_children.len() > 0 {
                try!(self.set_active_node(floating_children[0]));
            }
            Ok(())
        }
    }

    /// Normalizes the geometry of a view to be the same size as it's siblings,
    /// based on the parent container's layout, at the 0 point of the parent container.
    /// Note this does not auto-tile, only modifies this one view.
    ///
    /// Useful if a container's children want to be evenly distributed, or a new view
    /// is being added.
    pub fn normalize_view(&mut self, view: WlcView) {
        if let Some(view_ix) = self.tree.descendant_with_handle(self.tree.root_ix(), &view) {
            self.normalize_container(view_ix);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-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.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios"), not(target_os = "openbsd")))]
mod imp {
    use self::OsRngInner::*;

    use fs::File;
    use io;
    use libc;
    use mem;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use sys::os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc",
                  target_arch = "powerpc64")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;
        #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
        const NR_GETRANDOM: libc::c_long = 359;
        #[cfg(target_arch = "aarch64")]
        const NR_GETRANDOM: libc::c_long = 278;

        const GRND_NONBLOCK: libc::c_uint = 0x0001;

        unsafe {
            libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc",
                      target_arch = "powerpc64"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        while read < v.len() {
            let result = getrandom(&mut v[read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else if err == libc::EAGAIN {
                    let reader = File::open("/dev/urandom").expect("Unable to open /dev/urandom");
                    let mut reader_rng = ReaderRng::new(reader);
                    reader_rng.fill_bytes(& mut v[read..]);
                    read += v.len() as usize;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as usize;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8; 4] = [0; 4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8; 8] = [0; 8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc",
                  target_arch = "powerpc64")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, Ordering};
        use sync::Once;

        static CHECKER: Once = Once::new();
        static AVAILABLE: AtomicBool = AtomicBool::new(false);

        CHECKER.call_once(|| {
            let mut buf: [u8; 0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = io::Error::last_os_error().raw_os_error();
                err != Some(libc::ENOSYS)
            } else {
                true
            };
            AVAILABLE.store(available, Ordering::Relaxed);
        });

        AVAILABLE.load(Ordering::Relaxed)
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc",
                      target_arch = "powerpc64"))))]
    fn is_getrandom_available() -> bool { false }

    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = File::open("/dev/urandom")?;
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "openbsd")]
mod imp {
    use io;
    use libc;
    use mem;
    use sys::os::errno;
    use rand::Rng;

    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            // getentropy(2) permits a maximum buffer size of 256 bytes
            for s in v.chunks_mut(256) {
                let ret = unsafe {
                    libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len())
                };
                if ret == -1 {
                    panic!("unexpected getentropy error: {}", errno());
                }
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    use io;
    use mem;
    use ptr;
    use rand::Rng;
    use libc::{c_int, size_t};

    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    enum SecRandom {}

    #[allow(non_upper_case_globals)]
    const kSecRandomDefault: *const SecRandom = ptr::null();

    #[link(name = "Security", kind = "framework")]
    #[cfg(not(cargobuild))]
    extern {}

    extern {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t,
                                   v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}",
                       io::Error::last_os_error());
            }
        }
    }
}
<commit_msg>rand: add comments about getrandom() fallback<commit_after>// Copyright 2013-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.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios"), not(target_os = "openbsd")))]
mod imp {
    use self::OsRngInner::*;

    use fs::File;
    use io;
    use libc;
    use mem;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use sys::os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc",
                  target_arch = "powerpc64")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;
        #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
        const NR_GETRANDOM: libc::c_long = 359;
        #[cfg(target_arch = "aarch64")]
        const NR_GETRANDOM: libc::c_long = 278;

        const GRND_NONBLOCK: libc::c_uint = 0x0001;

        unsafe {
            libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc",
                      target_arch = "powerpc64"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        while read < v.len() {
            let result = getrandom(&mut v[read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else if err == libc::EAGAIN {
                    // if getrandom() returns EAGAIN it would have blocked
                    // because the non-blocking pool (urandom) has not
                    // initialized in the kernel yet due to a lack of entropy
                    // the fallback we do here is to avoid blocking applications
                    // which could depend on this call without ever knowing
                    // they do and don't have a work around. The PRNG of
                    // /dev/urandom will still be used but not over a completely
                    // full entropy pool
                    let reader = File::open("/dev/urandom").expect("Unable to open /dev/urandom");
                    let mut reader_rng = ReaderRng::new(reader);
                    reader_rng.fill_bytes(& mut v[read..]);
                    read += v.len() as usize;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as usize;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8; 4] = [0; 4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8; 8] = [0; 8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc",
                  target_arch = "powerpc64")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, Ordering};
        use sync::Once;

        static CHECKER: Once = Once::new();
        static AVAILABLE: AtomicBool = AtomicBool::new(false);

        CHECKER.call_once(|| {
            let mut buf: [u8; 0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = io::Error::last_os_error().raw_os_error();
                err != Some(libc::ENOSYS)
            } else {
                true
            };
            AVAILABLE.store(available, Ordering::Relaxed);
        });

        AVAILABLE.load(Ordering::Relaxed)
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc",
                      target_arch = "powerpc64"))))]
    fn is_getrandom_available() -> bool { false }

    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = File::open("/dev/urandom")?;
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "openbsd")]
mod imp {
    use io;
    use libc;
    use mem;
    use sys::os::errno;
    use rand::Rng;

    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            // getentropy(2) permits a maximum buffer size of 256 bytes
            for s in v.chunks_mut(256) {
                let ret = unsafe {
                    libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len())
                };
                if ret == -1 {
                    panic!("unexpected getentropy error: {}", errno());
                }
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    use io;
    use mem;
    use ptr;
    use rand::Rng;
    use libc::{c_int, size_t};

    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    enum SecRandom {}

    #[allow(non_upper_case_globals)]
    const kSecRandomDefault: *const SecRandom = ptr::null();

    #[link(name = "Security", kind = "framework")]
    #[cfg(not(cargobuild))]
    extern {}

    extern {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t,
                                   v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}",
                       io::Error::last_os_error());
            }
        }
    }
}
<|endoftext|>


<commit_before>use serenity::client::{Context, EventHandler};
use serenity::model::guild::Guild;

/// Extra functionality for big boi guilds.
///
/// When big boi guilds are sent in the Ready event, only their online members are sent. This makes
/// the bot request offline members, as well, or else the bot will never know their join times,
/// breaking features of the bot.
pub struct GuildsExt;

impl EventHandler for GuildsExt {
  fn guild_create(&self, ctx: Context, guild: Guild, new: bool) {
    if new {
      return;
    }
    if !guild.is_large() {
      return;
    }

    info!("Asking for offline users of {} ({})", guild.name, guild.id);
    ctx.shard.chunk_guilds(vec![guild.id], None, None);
  }
}
<commit_msg>refactor: be more concise<commit_after>use serenity::client::{Context, EventHandler};
use serenity::model::guild::Guild;

/// Extra functionality for big boi guilds.
///
/// When big boi guilds are sent in the Ready event, only their online members are sent. This makes
/// the bot request offline members, as well, or else the bot will never know their join times,
/// breaking features of the bot.
pub struct GuildsExt;

impl EventHandler for GuildsExt {
  fn guild_create(&self, ctx: Context, guild: Guild, new: bool) {
    if new || !guild.is_large() {
      return;
    }

    info!("Asking for offline users of {} ({})", guild.name, guild.id);
    ctx.shard.chunk_guilds(vec![guild.id], None, None);
  }
}
<|endoftext|>