<commit_before>use crate::utils::{
    is_adjusted, is_type_diagnostic_item, match_path, match_trait_method, match_var, paths, remove_blocks,
    span_lint_and_sugg,
};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Body, Expr, ExprKind, Pat, PatKind, QPath, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// **What it does:** Checks for instances of `map(f)` where `f` is the identity function.
    ///
    /// **Why is this bad?** It can be written more concisely without the call to `map`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// let x = [1, 2, 3];
    /// let y: Vec<_> = x.iter().map(|x| x).map(|x| 2*x).collect();
    /// ```
    /// Use instead:
    /// ```rust
    /// let x = [1, 2, 3];
    /// let y: Vec<_> = x.iter().map(|x| 2*x).collect();
    /// ```
    pub MAP_IDENTITY,
    complexity,
    "using iterator.map(|x| x)"
}

declare_lint_pass!(MapIdentity => [MAP_IDENTITY]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapIdentity {
    fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
        if expr.span.from_expansion() {
            return;
        }

        if_chain! {
            if let Some([caller, func]) = get_map_argument(cx, expr);
            if is_expr_identity_function(cx, func);
            then {
                span_lint_and_sugg(
                    cx,
                    MAP_IDENTITY,
                    expr.span.trim_start(caller.span).unwrap(),
                    "unnecessary map of the identity function",
                    "remove the call to `map`",
                    String::new(),
                    Applicability::MachineApplicable
                )
            }
        }
    }
}

/// Returns the arguments passed into map() if the expression is a method call to
/// map(). Otherwise, returns None.
fn get_map_argument<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option<&'a [Expr<'a>]> {
    if_chain! {
        if let ExprKind::MethodCall(ref method, _, ref args) = expr.kind;
        if args.len() == 2 && method.ident.as_str() == "map";
        let caller_ty = cx.tables.expr_ty(&args[0]);
        if match_trait_method(cx, expr, &paths::ITERATOR)
            || is_type_diagnostic_item(cx, caller_ty, sym!(result_type))
            || is_type_diagnostic_item(cx, caller_ty, sym!(option_type));
        then {
            Some(args)
        } else {
            None
        }
    }
}

/// Checks if an expression represents the identity function
/// Only examines closures and `std::convert::identity`
fn is_expr_identity_function(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
    match expr.kind {
        ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)),
        ExprKind::Path(QPath::Resolved(_, ref path)) => match_path(path, &paths::STD_CONVERT_IDENTITY),
        _ => false,
    }
}

/// Checks if a function's body represents the identity function
/// Looks for bodies of the form `|x| x`, `|x| return x`, `|x| { return x }` or `|x| {
/// return x; }`
fn is_body_identity_function(cx: &LateContext<'_, '_>, func: &Body<'_>) -> bool {
    let params = func.params;
    let body = remove_blocks(&func.value);

    // if there's less/more than one parameter, then it is not the identity function
    if params.len() != 1 {
        return false;
    }

    match body.kind {
        ExprKind::Path(QPath::Resolved(None, _)) => match_expr_param(cx, body, params[0].pat),
        ExprKind::Ret(Some(ref ret_val)) => match_expr_param(cx, ret_val, params[0].pat),
        ExprKind::Block(ref block, _) => {
            if_chain! {
                if block.stmts.len() == 1;
                if let StmtKind::Semi(ref expr) | StmtKind::Expr(ref expr) = block.stmts[0].kind;
                if let ExprKind::Ret(Some(ref ret_val)) = expr.kind;
                then {
                    match_expr_param(cx, ret_val, params[0].pat)
                } else {
                    false
                }
            }
        },
        _ => false,
    }
}

/// Returns true iff an expression returns the same thing as a parameter's pattern
fn match_expr_param(cx: &LateContext<'_, '_>, expr: &Expr<'_>, pat: &Pat<'_>) -> bool {
    if let PatKind::Binding(_, _, ident, _) = pat.kind {
        match_var(expr, ident.name) && !(cx.tables.hir_owner == Some(expr.hir_id.owner) && is_adjusted(cx, expr))
    } else {
        false
    }
}
<commit_msg>Fix pattern match of ExprKind::MethodCall<commit_after>use crate::utils::{
    is_adjusted, is_type_diagnostic_item, match_path, match_trait_method, match_var, paths, remove_blocks,
    span_lint_and_sugg,
};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Body, Expr, ExprKind, Pat, PatKind, QPath, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// **What it does:** Checks for instances of `map(f)` where `f` is the identity function.
    ///
    /// **Why is this bad?** It can be written more concisely without the call to `map`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// let x = [1, 2, 3];
    /// let y: Vec<_> = x.iter().map(|x| x).map(|x| 2*x).collect();
    /// ```
    /// Use instead:
    /// ```rust
    /// let x = [1, 2, 3];
    /// let y: Vec<_> = x.iter().map(|x| 2*x).collect();
    /// ```
    pub MAP_IDENTITY,
    complexity,
    "using iterator.map(|x| x)"
}

declare_lint_pass!(MapIdentity => [MAP_IDENTITY]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapIdentity {
    fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
        if expr.span.from_expansion() {
            return;
        }

        if_chain! {
            if let Some([caller, func]) = get_map_argument(cx, expr);
            if is_expr_identity_function(cx, func);
            then {
                span_lint_and_sugg(
                    cx,
                    MAP_IDENTITY,
                    expr.span.trim_start(caller.span).unwrap(),
                    "unnecessary map of the identity function",
                    "remove the call to `map`",
                    String::new(),
                    Applicability::MachineApplicable
                )
            }
        }
    }
}

/// Returns the arguments passed into map() if the expression is a method call to
/// map(). Otherwise, returns None.
fn get_map_argument<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option<&'a [Expr<'a>]> {
    if_chain! {
        if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind;
        if args.len() == 2 && method.ident.as_str() == "map";
        let caller_ty = cx.tables.expr_ty(&args[0]);
        if match_trait_method(cx, expr, &paths::ITERATOR)
            || is_type_diagnostic_item(cx, caller_ty, sym!(result_type))
            || is_type_diagnostic_item(cx, caller_ty, sym!(option_type));
        then {
            Some(args)
        } else {
            None
        }
    }
}

/// Checks if an expression represents the identity function
/// Only examines closures and `std::convert::identity`
fn is_expr_identity_function(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
    match expr.kind {
        ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)),
        ExprKind::Path(QPath::Resolved(_, ref path)) => match_path(path, &paths::STD_CONVERT_IDENTITY),
        _ => false,
    }
}

/// Checks if a function's body represents the identity function
/// Looks for bodies of the form `|x| x`, `|x| return x`, `|x| { return x }` or `|x| {
/// return x; }`
fn is_body_identity_function(cx: &LateContext<'_, '_>, func: &Body<'_>) -> bool {
    let params = func.params;
    let body = remove_blocks(&func.value);

    // if there's less/more than one parameter, then it is not the identity function
    if params.len() != 1 {
        return false;
    }

    match body.kind {
        ExprKind::Path(QPath::Resolved(None, _)) => match_expr_param(cx, body, params[0].pat),
        ExprKind::Ret(Some(ref ret_val)) => match_expr_param(cx, ret_val, params[0].pat),
        ExprKind::Block(ref block, _) => {
            if_chain! {
                if block.stmts.len() == 1;
                if let StmtKind::Semi(ref expr) | StmtKind::Expr(ref expr) = block.stmts[0].kind;
                if let ExprKind::Ret(Some(ref ret_val)) = expr.kind;
                then {
                    match_expr_param(cx, ret_val, params[0].pat)
                } else {
                    false
                }
            }
        },
        _ => false,
    }
}

/// Returns true iff an expression returns the same thing as a parameter's pattern
fn match_expr_param(cx: &LateContext<'_, '_>, expr: &Expr<'_>, pat: &Pat<'_>) -> bool {
    if let PatKind::Binding(_, _, ident, _) = pat.kind {
        match_var(expr, ident.name) && !(cx.tables.hir_owner == Some(expr.hir_id.owner) && is_adjusted(cx, expr))
    } else {
        false
    }
}
<|endoftext|>


<commit_before>use index::btree::dump::dump_tree;
use index::btree::external::ExtNode;
use index::btree::internal::InNode;
use index::btree::node::is_node_locked;
use index::btree::node::read_node;
use index::btree::node::read_unchecked;
use index::btree::node::write_node;
use index::btree::node::write_non_empty;
use index::btree::node::write_targeted;
use index::btree::node::EmptyNode;
use index::btree::node::Node;
use index::btree::node::NodeData;
use index::btree::node::NodeWriteGuard;
use index::btree::search::mut_search;
use index::btree::search::MutSearchResult;
use index::btree::LevelTree;
use index::btree::NodeCellRef;
use index::btree::{external, BPlusTree};
use index::lsmtree::tree::{LEVEL_2, LEVEL_3, LEVEL_PAGE_DIFF_MULTIPLIER};
use index::EntryKey;
use index::Slice;
use itertools::Itertools;
use smallvec::SmallVec;
use std::cmp::min;
use std::collections::{BTreeSet, HashMap, HashSet};
use std::fmt::Debug;
use std::mem;
use std::sync::atomic::Ordering::Relaxed;
use std::sync::Arc;

enum Selection<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    Selected(Vec<NodeWriteGuard<KS, PS>>),
    Innode(NodeCellRef),
}

struct KeyAltered {
    new_key: EntryKey,
    ptr: NodeCellRef,
}

fn select<KS, PS>(node: &NodeCellRef) -> Vec<NodeWriteGuard<KS, PS>>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let search = mut_search::<KS, PS>(node, &smallvec!());
    match search {
        MutSearchResult::External => {
            let first_node = write_node(node);
            let mut collected_keys = first_node.len();
            let mut collected = vec![first_node];
            let target_keys = min(KS::slice_len() * LEVEL_PAGE_DIFF_MULTIPLIER, LEVEL_3);
            let target_guards = LEVEL_2;
            while collected_keys < target_keys && collected.len() < target_guards {
                let right = write_node(
                    collected
                        .last_mut()
                        .unwrap()
                        .right_ref_mut_no_empty()
                        .unwrap(),
                );
                if right.is_none() {
                    break;
                } else {
                    collected_keys += right.len();
                    collected.push(right);
                }
            }
            return collected;
        }
        MutSearchResult::Internal(node) => select::<KS, PS>(&node),
    }
}

fn prune_selected<'a, KS, PS>(node: &NodeCellRef, bound: &EntryKey) -> Vec<KeyAltered>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let first_search = mut_search::<KS, PS>(node, &smallvec!());
    let extra_works = match first_search {
        MutSearchResult::Internal(sub_node_ref) => {
            let sub_node = read_unchecked::<KS, PS>(&sub_node_ref);
            if !sub_node.is_empty_node() && !sub_node.is_ext() {
                prune_selected::<KS, PS>(&sub_node_ref, bound)
            } else {
                vec![]
            }
        }
        MutSearchResult::External => unreachable!(),
    };
    let mut prev_node_guard: Option<NodeWriteGuard<KS, PS>> = None;
    let mut page = write_node::<KS, PS>(&node);
    let mut next_live_ptrs = None;
    let mut altered_list = vec![];
    let mut empty_nodes = vec![];
    let is_altered = |ptr: &NodeCellRef| extra_works.iter().find(|a| a.ptr.ptr_eq(ptr));
    let select_live = |page: &NodeWriteGuard<KS, PS>| {
        page.innode().ptrs.as_slice_immute()[..page.len() + 1]
            .iter()
            .enumerate()
            .filter_map(|(i, sub_level)| {
                if !read_unchecked::<KS, PS>(sub_level).is_empty_node() {
                    Some((i, sub_level.clone()))
                } else {
                    None
                }
            })
            .collect()
    };
    let mut next_non_empty = |page: &NodeWriteGuard<KS, PS>, empty_nodes: &mut Vec<_>| {
        let mut next = page.right_ref().cloned();
        while let Some(next_ref) = next {
            let guard = write_node::<KS, PS>(&next_ref);
            if guard.is_none() {
                return None;
            }
            next = guard.right_ref().cloned();
            let live_ptrs: HashMap<_, _> = select_live(&guard);
            if live_ptrs.is_empty() {
                empty_nodes.push(guard);
            } else {
                return Some((guard, live_ptrs));
            }
        }
        unreachable!()
    };
    let preserve_live = |innode: &mut InNode<KS, PS>,
                         node_ref: &NodeCellRef,
                         live_ptrs: HashMap<usize, NodeCellRef>,
                         altered_list: &mut Vec<KeyAltered>| {
        let mut new_keys = KS::init();
        let mut new_ptrs = PS::init();
        {
            let keys: Vec<&mut _> = innode.keys.as_slice()[..innode.len]
                .iter_mut()
                .enumerate()
                .filter(|(i, _)| live_ptrs.contains_key(&i))
                .map(|(_, k)| k)
                .collect();
            debug!("Prune filtered page have keys {:?}", &keys);
            debug_assert_eq!(live_ptrs.len(), keys.len() + 1);
            innode.len = keys.len();
            let new_keys = new_keys.as_slice();
            let new_ptrs = new_ptrs.as_slice();
            for (i, key) in keys.into_iter().enumerate() {
                debug_assert!(key > &mut smallvec!(0));
                mem::swap(&mut new_keys[i], key);
            }
            for (i, (_, ptr)) in live_ptrs.into_iter().enumerate() {
                debug_assert!(!ptr.is_default());
                if let Some(altered) = is_altered(&ptr) {
                    new_keys[i] = altered.new_key.clone();
                    if i == 0 {
                        altered_list.push(KeyAltered {
                            new_key: altered.new_key.clone(),
                            ptr: node_ref.clone(),
                        })
                    }
                }
                mem::replace(&mut new_ptrs[i], ptr);
            }
        }
        innode.keys = new_keys;
        innode.ptrs = new_ptrs;
        innode.len == 0
    };
    loop {
        let page_right_ref = page.right_ref().unwrap().clone();
        if !page.is_empty_node() {
            let mut live_ptrs: HashMap<_, _> = next_live_ptrs.unwrap_or_else(|| select_live(&page));
            let is_empty = live_ptrs.is_empty();
            if !is_empty {
                let emptying = {
                    let page_ref = page.node_ref().clone();
                    let mut innode = page.innode_mut();
                    preserve_live(&mut innode, &page_ref, live_ptrs, &mut altered_list)
                };
                if emptying {
                    // current innode have one ptr and no keys
                    // need to merge with the right page
                    // if the right page is full, partial of the right page will be moved to the current page
                    // merging right page will also been cleaned
                    if let Some((mut next_guard, next_ptrs)) =
                        next_non_empty(&page, &mut empty_nodes)
                    {
                        let mid = next_guard.len() / 2;
                        let next_ref = next_guard.node_ref().clone();
                        let page_ref = page.node_ref().clone();
                        let mut page_innode = page.innode_mut();
                        let next_node_emptying = preserve_live(
                            &mut next_guard.innode_mut(),
                            &next_ref,
                            next_ptrs,
                            &mut altered_list,
                        );
                        page_innode.keys.as_slice()[0] = page_innode.right_bound.clone();
                        if next_guard.len() >= KS::slice_len() {
                            // will overflow if merged, have to rebalance right node contents with current node
                            let mut next_innode = next_guard.innode_mut();
                            let next_search_key = next_innode.keys.as_slice()[0].clone();
                            // move next node keys and ptrs to current node
                            for i in 0..mid {
                                mem::swap(
                                    &mut page_innode.keys.as_slice()[i + 1],
                                    &mut next_innode.keys.as_slice()[i],
                                );
                                mem::swap(
                                    &mut page_innode.ptrs.as_slice()[i + 1],
                                    &mut next_innode.ptrs.as_slice()[i],
                                );
                            }
                            for i in mid..next_innode.len {
                                next_innode.keys.as_slice().swap(i, i - mid);
                                next_innode.ptrs.as_slice().swap(i, i - mid);
                            }
                            next_innode.len -= mid;
                            page_innode.len += mid;
                            page_innode.right_bound =
                                mem::replace(&mut page_innode.keys.as_slice()[mid], smallvec!());
                            page_innode.len = 1 + mid;
                            altered_list.push(KeyAltered {
                                new_key: page_innode.right_bound.clone(),
                                ptr: next_ref,
                            });
                        } else {
                            // Can move right page contents to current node and empty next node
                            {
                                let mut next_innode = next_guard.innode_mut();
                                let next_node_len = next_innode.len;
                                for i in 0..next_innode.len {
                                    mem::swap(
                                        &mut page_innode.keys.as_slice()[i + 1],
                                        &mut next_innode.keys.as_slice()[i],
                                    );
                                    mem::swap(
                                        &mut page_innode.ptrs.as_slice()[i + 1],
                                        &mut next_innode.ptrs.as_slice()[i],
                                    );
                                }
                                mem::swap(
                                    &mut page_innode.ptrs.as_slice()[next_node_len + 1],
                                    &mut next_innode.ptrs.as_slice()[next_node_len],
                                );
                                page_innode.len = 1 + next_node_len;
                                page_innode.right = next_innode.right.clone();
                                page_innode.right_bound = next_innode.right_bound.clone();
                            }
                            *next_guard = NodeData::Empty(box EmptyNode {
                                left: None,
                                right: page_ref,
                            });
                        }
                    } else {
                        break;
                    }
                }
            }
            if let Some((next_page, ptrs)) = next_non_empty(&page, &mut empty_nodes) {
                if !is_empty {
                    if page.right_bound() >= bound {
                        break;
                    } else {
                        prev_node_guard = Some(page);
                    }
                } else {
                    empty_nodes.push(page);
                }
                page = next_page;
                next_live_ptrs = Some(ptrs);
            } else {
                break;
            }
        } else {
            unreachable!();
        }
    }
    let last_page_ref = page.node_ref();
    for empty in &mut empty_nodes {
        // make nodes empty and set its next ptr to last non empty node
        **empty = NodeData::Empty(box EmptyNode {
            left: None,
            right: last_page_ref.clone(),
        });
    }
    // Reverse the list so only latest pushed will take effect
    altered_list.reverse();
    altered_list
}

pub fn level_merge<KS, PS>(src_tree: &BPlusTree<KS, PS>, dest_tree: &LevelTree) -> usize
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let mut left_most_leaf_guards = select::<KS, PS>(&src_tree.get_root());
    let merge_page_len = left_most_leaf_guards.len();
    let mut num_keys_removed = 0;
    let left_most_id = left_most_leaf_guards.first().unwrap().ext_id();
    let prune_bound = left_most_leaf_guards.last().unwrap().right_bound().clone();

    debug!("Merge selected {} pages", left_most_leaf_guards.len());
    if cfg!(debug_assertions) {
        if left_most_id != src_tree.head_page_id {
            dump_tree(src_tree, "level_lsm_merge_failure_dump.json");
        }
    }
    debug_assert_eq!(
        left_most_id,
        src_tree.head_page_id,
        "{}",
        left_most_leaf_guards.first().unwrap().type_name()
    );

    // merge to dest_tree
    {
        let mut deleted_keys = src_tree.deleted.write();
        let mut merged_deleted_keys = vec![];
        let keys: Vec<EntryKey> = left_most_leaf_guards
            .iter()
            .filter(|&g| !g.is_empty_node())
            .map(|g| &g.keys()[..g.len()])
            .flatten()
            .filter(|&k| {
                if deleted_keys.contains(k) {
                    merged_deleted_keys.push(k.clone());
                    false
                } else {
                    true
                }
            })
            .cloned()
            .collect_vec();
        num_keys_removed = keys.len();
        debug!("Merge selected keys are {:?}", &keys);
        dest_tree.merge_with_keys(box keys);
        for rk in &merged_deleted_keys {
            deleted_keys.remove(rk);
        }
    }

    // adjust leaf left, right references
    {
        let right_right_most = left_most_leaf_guards
            .last()
            .unwrap()
            .right_ref()
            .unwrap()
            .clone();

        let left_left_most = left_most_leaf_guards
            .first()
            .unwrap()
            .left_ref()
            .unwrap()
            .clone();

        debug_assert!(read_unchecked::<KS, PS>(&left_left_most).is_none());
        debug_assert!(read_unchecked::<KS, PS>(&right_right_most).is_ext());
        debug_assert!(!Arc::ptr_eq(
            &right_right_most.inner,
            &left_most_leaf_guards.last().unwrap().node_ref().inner
        ));

        for mut g in &mut left_most_leaf_guards {
            external::make_deleted(&g.ext_id());
            **g = NodeData::Empty(box EmptyNode {
                left: Some(left_left_most.clone()),
                right: right_right_most.clone(),
            });
        }

        let mut new_first_node = write_node::<KS, PS>(&right_right_most);
        let mut new_first_node_ext = new_first_node.extnode_mut();
        new_first_node_ext.id = src_tree.head_page_id;
        new_first_node_ext.prev = left_left_most;

        debug_assert!(&new_first_node_ext.right_bound > &prune_bound);

        ExtNode::<KS, PS>::make_changed(&right_right_most, src_tree);
    }

    // cleanup upper level references
    prune_selected::<KS, PS>(&src_tree.get_root(), &prune_bound);

    src_tree.len.fetch_sub(num_keys_removed, Relaxed);

    merge_page_len
}
<commit_msg>trying to inspect the prune problem<commit_after>use index::btree::dump::dump_tree;
use index::btree::external::ExtNode;
use index::btree::internal::InNode;
use index::btree::node::is_node_locked;
use index::btree::node::read_node;
use index::btree::node::read_unchecked;
use index::btree::node::write_node;
use index::btree::node::write_non_empty;
use index::btree::node::write_targeted;
use index::btree::node::EmptyNode;
use index::btree::node::Node;
use index::btree::node::NodeData;
use index::btree::node::NodeWriteGuard;
use index::btree::search::mut_search;
use index::btree::search::MutSearchResult;
use index::btree::LevelTree;
use index::btree::NodeCellRef;
use index::btree::{external, BPlusTree};
use index::lsmtree::tree::{LEVEL_2, LEVEL_3, LEVEL_PAGE_DIFF_MULTIPLIER};
use index::EntryKey;
use index::Slice;
use itertools::Itertools;
use smallvec::SmallVec;
use std::cmp::min;
use std::collections::{BTreeSet, HashMap, HashSet};
use std::fmt::Debug;
use std::mem;
use std::sync::atomic::Ordering::Relaxed;
use std::sync::Arc;

enum Selection<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    Selected(Vec<NodeWriteGuard<KS, PS>>),
    Innode(NodeCellRef),
}

struct KeyAltered {
    new_key: EntryKey,
    ptr: NodeCellRef,
}

fn select<KS, PS>(node: &NodeCellRef) -> Vec<NodeWriteGuard<KS, PS>>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let search = mut_search::<KS, PS>(node, &smallvec!());
    match search {
        MutSearchResult::External => {
            let first_node = write_node(node);
            let mut collected_keys = first_node.len();
            let mut collected = vec![first_node];
            let target_keys = min(KS::slice_len() * LEVEL_PAGE_DIFF_MULTIPLIER, LEVEL_3);
            let target_guards = LEVEL_2;
            while collected_keys < target_keys && collected.len() < target_guards {
                let right = write_node(
                    collected
                        .last_mut()
                        .unwrap()
                        .right_ref_mut_no_empty()
                        .unwrap(),
                );
                if right.is_none() {
                    break;
                } else {
                    collected_keys += right.len();
                    collected.push(right);
                }
            }
            return collected;
        }
        MutSearchResult::Internal(node) => select::<KS, PS>(&node),
    }
}

fn prune_selected<'a, KS, PS>(node: &NodeCellRef, bound: &EntryKey, level: usize) -> Vec<KeyAltered>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let first_search = mut_search::<KS, PS>(node, &smallvec!());
    let extra_works = match first_search {
        MutSearchResult::Internal(sub_node_ref) => {
            let sub_node = read_unchecked::<KS, PS>(&sub_node_ref);
            if !sub_node.is_empty_node() && !sub_node.is_ext() {
                prune_selected::<KS, PS>(&sub_node_ref, bound, level + 1)
            } else {
                vec![]
            }
        }
        MutSearchResult::External => unreachable!(),
    };
    let mut prev_node_guard: Option<NodeWriteGuard<KS, PS>> = None;
    let mut page = write_node::<KS, PS>(&node);
    let mut next_live_ptrs = None;
    let mut altered_list = vec![];
    let mut empty_nodes = vec![];
    let is_altered = |ptr: &NodeCellRef| extra_works.iter().find(|a| a.ptr.ptr_eq(ptr));
    let select_live = |page: &NodeWriteGuard<KS, PS>| {
        page.innode().ptrs.as_slice_immute()[..page.len() + 1]
            .iter()
            .enumerate()
            .filter_map(|(i, sub_level)| {
                if !read_unchecked::<KS, PS>(sub_level).is_empty_node() {
                    Some((i, sub_level.clone()))
                } else {
                    None
                }
            })
            .collect()
    };
    let mut next_non_empty = |page: &NodeWriteGuard<KS, PS>, empty_nodes: &mut Vec<_>| {
        let mut next = page.right_ref().cloned();
        while let Some(next_ref) = next {
            let guard = write_node::<KS, PS>(&next_ref);
            if guard.is_none() {
                return None;
            }
            next = guard.right_ref().cloned();
            let live_ptrs: HashMap<_, _> = select_live(&guard);
            if live_ptrs.is_empty() {
                empty_nodes.push(guard);
            } else {
                return Some((guard, live_ptrs));
            }
        }
        unreachable!()
    };
    let preserve_live = |innode: &mut InNode<KS, PS>,
                         node_ref: &NodeCellRef,
                         live_ptrs: HashMap<usize, NodeCellRef>,
                         altered_list: &mut Vec<KeyAltered>| {
        debug!("preserving live ptrs - {}", level);
        let mut new_keys = KS::init();
        let mut new_ptrs = PS::init();
        {
            let keys: Vec<&mut _> = innode.keys.as_slice()[..innode.len]
                .iter_mut()
                .enumerate()
                .filter(|(i, _)| live_ptrs.contains_key(&i))
                .map(|(_, k)| k)
                .collect();
            debug!("Prune filtered page have keys {}, was {}, node right bound: {:?}, prune right bound {:?} - {}", keys.len(), innode.len, innode.right_bound, bound, level);
            debug_assert_eq!(live_ptrs.len(), keys.len() + 1);
            innode.len = keys.len();
            let new_keys = new_keys.as_slice();
            let new_ptrs = new_ptrs.as_slice();
            for (i, key) in keys.into_iter().enumerate() {
                debug_assert!(key > &mut smallvec!(0));
                mem::swap(&mut new_keys[i], key);
            }
            for (i, (_, ptr)) in live_ptrs.into_iter().enumerate() {
                debug_assert!(!ptr.is_default());
                if let Some(altered) = is_altered(&ptr) {
                    new_keys[i] = altered.new_key.clone();
                    if i == 0 {
                        altered_list.push(KeyAltered {
                            new_key: altered.new_key.clone(),
                            ptr: node_ref.clone(),
                        })
                    }
                }
                mem::replace(&mut new_ptrs[i], ptr);
            }
        }
        innode.keys = new_keys;
        innode.ptrs = new_ptrs;
        innode.len == 0
    };
    loop {
        let page_right_ref = page.right_ref().unwrap().clone();
        if !page.is_empty_node() {
            let mut live_ptrs: HashMap<_, _> = next_live_ptrs.unwrap_or_else(|| select_live(&page));
            let is_empty = live_ptrs.is_empty();
            if !is_empty {
                let emptying = {
                    let page_ref = page.node_ref().clone();
                    let mut innode = page.innode_mut();
                    preserve_live(&mut innode, &page_ref, live_ptrs, &mut altered_list)
                };
                if emptying {
                    // current innode have one ptr and no keys
                    // need to merge with the right page
                    // if the right page is full, partial of the right page will be moved to the current page
                    // merging right page will also been cleaned
                    debug!("node is emptying - {}", level);
                    if let Some((mut next_guard, next_ptrs)) =
                        next_non_empty(&page, &mut empty_nodes)
                    {
                        let mid = next_guard.len() / 2;
                        let next_ref = next_guard.node_ref().clone();
                        let page_ref = page.node_ref().clone();
                        let mut page_innode = page.innode_mut();
                        let next_node_emptying = preserve_live(
                            &mut next_guard.innode_mut(),
                            &next_ref,
                            next_ptrs,
                            &mut altered_list,
                        );
                        page_innode.keys.as_slice()[0] = page_innode.right_bound.clone();
                        if next_guard.len() >= KS::slice_len() {
                            // will overflow if merged, have to rebalance right node contents with current node
                            let mut next_innode = next_guard.innode_mut();
                            let next_search_key = next_innode.keys.as_slice()[0].clone();
                            // move next node keys and ptrs to current node
                            for i in 0..mid {
                                mem::swap(
                                    &mut page_innode.keys.as_slice()[i + 1],
                                    &mut next_innode.keys.as_slice()[i],
                                );
                                mem::swap(
                                    &mut page_innode.ptrs.as_slice()[i + 1],
                                    &mut next_innode.ptrs.as_slice()[i],
                                );
                            }
                            for i in mid..next_innode.len {
                                next_innode.keys.as_slice().swap(i, i - mid);
                                next_innode.ptrs.as_slice().swap(i, i - mid);
                            }
                            next_innode.len -= mid;
                            page_innode.len += mid;
                            page_innode.right_bound =
                                mem::replace(&mut page_innode.keys.as_slice()[mid], smallvec!());
                            page_innode.len = 1 + mid;
                            altered_list.push(KeyAltered {
                                new_key: page_innode.right_bound.clone(),
                                ptr: next_ref,
                            });
                        } else {
                            // Can move right page contents to current node and empty next node
                            {
                                let mut next_innode = next_guard.innode_mut();
                                let next_node_len = next_innode.len;
                                for i in 0..next_innode.len {
                                    mem::swap(
                                        &mut page_innode.keys.as_slice()[i + 1],
                                        &mut next_innode.keys.as_slice()[i],
                                    );
                                    mem::swap(
                                        &mut page_innode.ptrs.as_slice()[i + 1],
                                        &mut next_innode.ptrs.as_slice()[i],
                                    );
                                }
                                mem::swap(
                                    &mut page_innode.ptrs.as_slice()[next_node_len + 1],
                                    &mut next_innode.ptrs.as_slice()[next_node_len],
                                );
                                page_innode.len = 1 + next_node_len;
                                page_innode.right = next_innode.right.clone();
                                page_innode.right_bound = next_innode.right_bound.clone();
                            }
                            *next_guard = NodeData::Empty(box EmptyNode {
                                left: None,
                                right: page_ref,
                            });
                        }
                    } else {
                        break;
                    }
                }
            }
            if let Some((next_page, ptrs)) = next_non_empty(&page, &mut empty_nodes) {
                if !is_empty {
                    prev_node_guard = Some(page);
                } else {
                    empty_nodes.push(page);
                }
                page = next_page;
                next_live_ptrs = Some(ptrs);
            } else {
                debug!("Cannot find any right node to continue prune - {}", level);
                break;
            }
            if page.right_bound() >= bound {
                debug!("Out of bound to continue prune - {}", level);
                break;
            }
        } else {
            unreachable!();
        }
    }
    let last_page_ref = page.node_ref();
    for empty in &mut empty_nodes {
        // make nodes empty and set its next ptr to last non empty node
        **empty = NodeData::Empty(box EmptyNode {
            left: None,
            right: last_page_ref.clone(),
        });
    }
    // Reverse the list so only latest pushed will take effect
    altered_list.reverse();
    altered_list
}

pub fn level_merge<KS, PS>(src_tree: &BPlusTree<KS, PS>, dest_tree: &LevelTree) -> usize
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let mut left_most_leaf_guards = select::<KS, PS>(&src_tree.get_root());
    let merge_page_len = left_most_leaf_guards.len();
    let mut num_keys_removed = 0;
    let left_most_id = left_most_leaf_guards.first().unwrap().ext_id();
    let prune_bound = left_most_leaf_guards.last().unwrap().right_bound().clone();

    debug!("Merge selected {} pages", left_most_leaf_guards.len());
    if cfg!(debug_assertions) {
        if left_most_id != src_tree.head_page_id {
            dump_tree(src_tree, "level_lsm_merge_failure_dump.json");
        }
    }
    debug_assert_eq!(
        left_most_id,
        src_tree.head_page_id,
        "{}",
        left_most_leaf_guards.first().unwrap().type_name()
    );

    // merge to dest_tree
    {
        let mut deleted_keys = src_tree.deleted.write();
        let mut merged_deleted_keys = vec![];
        let keys: Vec<EntryKey> = left_most_leaf_guards
            .iter()
            .filter(|&g| !g.is_empty_node())
            .map(|g| &g.keys()[..g.len()])
            .flatten()
            .filter(|&k| {
                if deleted_keys.contains(k) {
                    merged_deleted_keys.push(k.clone());
                    false
                } else {
                    true
                }
            })
            .cloned()
            .collect_vec();
        num_keys_removed = keys.len();
        debug!("Merge selected keys {:?}", keys.len());
        dest_tree.merge_with_keys(box keys);
        for rk in &merged_deleted_keys {
            deleted_keys.remove(rk);
        }
    }

    // adjust leaf left, right references
    {
        let right_right_most = left_most_leaf_guards
            .last()
            .unwrap()
            .right_ref()
            .unwrap()
            .clone();

        let left_left_most = left_most_leaf_guards
            .first()
            .unwrap()
            .left_ref()
            .unwrap()
            .clone();

        debug_assert!(read_unchecked::<KS, PS>(&left_left_most).is_none());
        debug_assert!(read_unchecked::<KS, PS>(&right_right_most).is_ext());
        debug_assert!(!right_right_most.ptr_eq(left_most_leaf_guards.last().unwrap().node_ref()));

        for mut g in &mut left_most_leaf_guards {
            external::make_deleted(&g.ext_id());
            debug!("make deleted {:?}", g.ext_id());
            **g = NodeData::Empty(box EmptyNode {
                left: Some(left_left_most.clone()),
                right: right_right_most.clone(),
            });
        }

        let mut new_first_node = write_node::<KS, PS>(&right_right_most);
        let mut new_first_node_ext = new_first_node.extnode_mut();
        debug!(
            "Right most original id is {:?}, now is {:?}",
            new_first_node_ext.id, src_tree.head_page_id
        );
        debug!(
            "New first node right is {:?}",
            read_unchecked::<KS, PS>(&new_first_node_ext.next).ext_id()
        );
        new_first_node_ext.id = src_tree.head_page_id;
        new_first_node_ext.prev = left_left_most;

        debug_assert!(&new_first_node_ext.right_bound > &prune_bound);

        ExtNode::<KS, PS>::make_changed(&right_right_most, src_tree);
    }

    // cleanup upper level references
    prune_selected::<KS, PS>(&src_tree.get_root(), &prune_bound, 0);

    src_tree.len.fetch_sub(num_keys_removed, Relaxed);

    if cfg!(debug_assertions) {
        dump_tree(src_tree, "last_merged_tree_dump.json");
    }
    debug!("Merge completed");

    merge_page_len
}
<|endoftext|>


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

use hir::def_id::DefId;
use util::nodemap::NodeMap;
use syntax::ast;
use syntax::ext::base::MacroKind;
use syntax_pos::Span;
use hir;

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum CtorKind {
    // Constructor function automatically created by a tuple struct/variant.
    Fn,
    // Constructor constant automatically created by a unit struct/variant.
    Const,
    // Unusable name in value namespace created by a struct variant.
    Fictive,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Def {
    // Type namespace
    Mod(DefId),
    Struct(DefId), // DefId refers to NodeId of the struct itself
    Union(DefId),
    Enum(DefId),
    Variant(DefId),
    Trait(DefId),
    TyAlias(DefId),
    AssociatedTy(DefId),
    PrimTy(hir::PrimTy),
    TyParam(DefId),
    SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),

    // Value namespace
    Fn(DefId),
    Const(DefId),
    Static(DefId, bool /* is_mutbl */),
    StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
    VariantCtor(DefId, CtorKind),
    Method(DefId),
    AssociatedConst(DefId),
    Local(DefId),
    Upvar(DefId,        // def id of closed over local
          usize,        // index in the freevars list of the closure
          ast::NodeId), // expr node that creates the closure
    Label(ast::NodeId),

    // Macro namespace
    Macro(DefId, MacroKind),

    GlobalAsm(DefId),

    // Both namespaces
    Err,
}

/// The result of resolving a path before lowering to HIR.
/// `base_def` is definition of resolved part of the
/// path, `unresolved_segments` is the number of unresolved
/// segments.
///     module::Type::AssocX::AssocY::MethodOrAssocType
///     ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///     base_def      unresolved_segments = 3
///
///     <T as Trait>::AssocX::AssocY::MethodOrAssocType
///           ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
///           base_def        unresolved_segments = 2
#[derive(Copy, Clone, Debug)]
pub struct PathResolution {
    base_def: Def,
    unresolved_segments: usize,
}

impl PathResolution {
    pub fn new(def: Def) -> Self {
        PathResolution { base_def: def, unresolved_segments: 0 }
    }

    pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self {
        if def == Def::Err { unresolved_segments = 0 }
        PathResolution { base_def: def, unresolved_segments: unresolved_segments }
    }

    #[inline]
    pub fn base_def(&self) -> Def {
        self.base_def
    }

    #[inline]
    pub fn unresolved_segments(&self) -> usize {
        self.unresolved_segments
    }

    pub fn kind_name(&self) -> &'static str {
        if self.unresolved_segments != 0 {
            "associated item"
        } else {
            self.base_def.kind_name()
        }
    }
}

// Definition mapping
pub type DefMap = NodeMap<PathResolution>;
// This is the replacement export map. It maps a module to all of the exports
// within.
pub type ExportMap = NodeMap<Vec<Export>>;

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Export {
    pub ident: ast::Ident, // The name of the target.
    pub def: Def, // The definition of the target.
    pub span: Span, // The span of the target definition.
}

impl CtorKind {
    pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
        match *vdata {
            ast::VariantData::Tuple(..) => CtorKind::Fn,
            ast::VariantData::Unit(..) => CtorKind::Const,
            ast::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
    pub fn from_hir(vdata: &hir::VariantData) -> CtorKind {
        match *vdata {
            hir::VariantData::Tuple(..) => CtorKind::Fn,
            hir::VariantData::Unit(..) => CtorKind::Const,
            hir::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
}

impl Def {
    pub fn def_id(&self) -> DefId {
        match *self {
            Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
            Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) |
            Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
            Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
            Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id, ..) |
            Def::GlobalAsm(id) => {
                id
            }

            Def::Label(..)  |
            Def::PrimTy(..) |
            Def::SelfTy(..) |
            Def::Err => {
                bug!("attempted .def_id() on invalid def: {:?}", self)
            }
        }
    }

    pub fn kind_name(&self) -> &'static str {
        match *self {
            Def::Fn(..) => "function",
            Def::Mod(..) => "module",
            Def::Static(..) => "static",
            Def::Variant(..) => "variant",
            Def::VariantCtor(.., CtorKind::Fn) => "tuple variant",
            Def::VariantCtor(.., CtorKind::Const) => "unit variant",
            Def::VariantCtor(.., CtorKind::Fictive) => "struct variant",
            Def::Enum(..) => "enum",
            Def::TyAlias(..) => "type alias",
            Def::AssociatedTy(..) => "associated type",
            Def::Struct(..) => "struct",
            Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
            Def::StructCtor(.., CtorKind::Const) => "unit struct",
            Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
            Def::Union(..) => "union",
            Def::Trait(..) => "trait",
            Def::Method(..) => "method",
            Def::Const(..) => "constant",
            Def::AssociatedConst(..) => "associated constant",
            Def::TyParam(..) => "type parameter",
            Def::PrimTy(..) => "builtin type",
            Def::Local(..) => "local variable",
            Def::Upvar(..) => "closure capture",
            Def::Label(..) => "label",
            Def::SelfTy(..) => "self type",
            Def::Macro(..) => "macro",
            Def::GlobalAsm(..) => "global asm",
            Def::Err => "unresolved item",
        }
    }
}
<commit_msg>Better docs for librustc/hir/def.rs<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hir::def_id::DefId;
use util::nodemap::NodeMap;
use syntax::ast;
use syntax::ext::base::MacroKind;
use syntax_pos::Span;
use hir;

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum CtorKind {
    /// Constructor function automatically created by a tuple struct/variant.
    Fn,
    /// Constructor constant automatically created by a unit struct/variant.
    Const,
    /// Unusable name in value namespace created by a struct variant.
    Fictive,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Def {
    // Type namespace
    Mod(DefId),
    Struct(DefId), // DefId refers to NodeId of the struct itself
    Union(DefId),
    Enum(DefId),
    Variant(DefId),
    Trait(DefId),
    TyAlias(DefId),
    AssociatedTy(DefId),
    PrimTy(hir::PrimTy),
    TyParam(DefId),
    SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),

    // Value namespace
    Fn(DefId),
    Const(DefId),
    Static(DefId, bool /* is_mutbl */),
    StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
    VariantCtor(DefId, CtorKind),
    Method(DefId),
    AssociatedConst(DefId),
    Local(DefId),
    Upvar(DefId,        // def id of closed over local
          usize,        // index in the freevars list of the closure
          ast::NodeId), // expr node that creates the closure
    Label(ast::NodeId),

    // Macro namespace
    Macro(DefId, MacroKind),

    GlobalAsm(DefId),

    // Both namespaces
    Err,
}

/// The result of resolving a path before lowering to HIR.
/// `base_def` is definition of resolved part of the
/// path, `unresolved_segments` is the number of unresolved
/// segments.
///     module::Type::AssocX::AssocY::MethodOrAssocType
///     ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///     base_def      unresolved_segments = 3
///
///     <T as Trait>::AssocX::AssocY::MethodOrAssocType
///           ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
///           base_def        unresolved_segments = 2
#[derive(Copy, Clone, Debug)]
pub struct PathResolution {
    base_def: Def,
    unresolved_segments: usize,
}

impl PathResolution {
    pub fn new(def: Def) -> Self {
        PathResolution { base_def: def, unresolved_segments: 0 }
    }

    pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self {
        if def == Def::Err { unresolved_segments = 0 }
        PathResolution { base_def: def, unresolved_segments: unresolved_segments }
    }

    #[inline]
    pub fn base_def(&self) -> Def {
        self.base_def
    }

    #[inline]
    pub fn unresolved_segments(&self) -> usize {
        self.unresolved_segments
    }

    pub fn kind_name(&self) -> &'static str {
        if self.unresolved_segments != 0 {
            "associated item"
        } else {
            self.base_def.kind_name()
        }
    }
}

/// Definition mapping
pub type DefMap = NodeMap<PathResolution>;

/// This is the replacement export map. It maps a module to all of the exports
/// within.
pub type ExportMap = NodeMap<Vec<Export>>;

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Export {
    /// The name of the target.
    pub ident: ast::Ident,
    /// The definition of the target.
    pub def: Def,
    /// The span of the target definition.
    pub span: Span,
}

impl CtorKind {
    pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
        match *vdata {
            ast::VariantData::Tuple(..) => CtorKind::Fn,
            ast::VariantData::Unit(..) => CtorKind::Const,
            ast::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
    pub fn from_hir(vdata: &hir::VariantData) -> CtorKind {
        match *vdata {
            hir::VariantData::Tuple(..) => CtorKind::Fn,
            hir::VariantData::Unit(..) => CtorKind::Const,
            hir::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
}

impl Def {
    pub fn def_id(&self) -> DefId {
        match *self {
            Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
            Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) |
            Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
            Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
            Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id, ..) |
            Def::GlobalAsm(id) => {
                id
            }

            Def::Label(..)  |
            Def::PrimTy(..) |
            Def::SelfTy(..) |
            Def::Err => {
                bug!("attempted .def_id() on invalid def: {:?}", self)
            }
        }
    }

    /// A human readable kind name
    pub fn kind_name(&self) -> &'static str {
        match *self {
            Def::Fn(..) => "function",
            Def::Mod(..) => "module",
            Def::Static(..) => "static",
            Def::Variant(..) => "variant",
            Def::VariantCtor(.., CtorKind::Fn) => "tuple variant",
            Def::VariantCtor(.., CtorKind::Const) => "unit variant",
            Def::VariantCtor(.., CtorKind::Fictive) => "struct variant",
            Def::Enum(..) => "enum",
            Def::TyAlias(..) => "type alias",
            Def::AssociatedTy(..) => "associated type",
            Def::Struct(..) => "struct",
            Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
            Def::StructCtor(.., CtorKind::Const) => "unit struct",
            Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
            Def::Union(..) => "union",
            Def::Trait(..) => "trait",
            Def::Method(..) => "method",
            Def::Const(..) => "constant",
            Def::AssociatedConst(..) => "associated constant",
            Def::TyParam(..) => "type parameter",
            Def::PrimTy(..) => "builtin type",
            Def::Local(..) => "local variable",
            Def::Upvar(..) => "closure capture",
            Def::Label(..) => "label",
            Def::SelfTy(..) => "self type",
            Def::Macro(..) => "macro",
            Def::GlobalAsm(..) => "global asm",
            Def::Err => "unresolved item",
        }
    }
}
<|endoftext|>


<commit_before>//! The "main crate" of the Rust compiler. This crate contains common
//! type definitions that are used by the other crates in the rustc
//! "family". Some prominent examples (note that each of these modules
//! has their own README with further details).
//!
//! - **HIR.** The "high-level (H) intermediate representation (IR)" is
//!   defined in the `hir` module.
//! - **MIR.** The "mid-level (M) intermediate representation (IR)" is
//!   defined in the `mir` module. This module contains only the
//!   *definition* of the MIR; the passes that transform and operate
//!   on MIR are found in `librustc_mir` crate.
//! - **Types.** The internal representation of types used in rustc is
//!   defined in the `ty` module. This includes the **type context**
//!   (or `tcx`), which is the central context during most of
//!   compilation, containing the interners and other things.
//!
//! For more information about how rustc works, see the [rustc dev guide].
//!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/
//!
//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(array_windows)]
#![feature(assoc_char_funcs)]
#![feature(backtrace)]
#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(cmp_min_max_by)]
#![feature(const_fn)]
#![feature(const_panic)]
#![feature(core_intrinsics)]
#![feature(discriminant_kind)]
#![feature(never_type)]
#![feature(extern_types)]
#![feature(nll)]
#![feature(once_cell)]
#![feature(option_expect_none)]
#![feature(or_patterns)]
#![feature(min_specialization)]
#![feature(trusted_len)]
#![feature(test)]
#![feature(in_band_lifetimes)]
#![feature(crate_visibility_modifier)]
#![feature(associated_type_bounds)]
#![feature(rustc_attrs)]
#![feature(int_error_matching)]
#![feature(half_open_range_patterns)]
#![feature(exclusive_range_pattern)]
#![feature(control_flow_enum)]
#![feature(associated_type_defaults)]
#![recursion_limit = "512"]

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate rustc_macros;
#[macro_use]
extern crate rustc_data_structures;
#[macro_use]
extern crate tracing;
#[macro_use]
extern crate smallvec;

#[cfg(test)]
mod tests;

#[macro_use]
mod macros;

#[macro_use]
pub mod query;

#[macro_use]
pub mod arena;
pub mod dep_graph;
pub mod hir;
pub mod ich;
pub mod infer;
pub mod lint;
pub mod middle;
pub mod mir;
pub mod traits;
pub mod ty;

pub mod util {
    pub mod bug;
    pub mod common;
}

// Allows macros to refer to this crate as `::rustc_middle`
extern crate self as rustc_middle;
<commit_msg>docs: Fix outdated crate reference<commit_after>//! The "main crate" of the Rust compiler. This crate contains common
//! type definitions that are used by the other crates in the rustc
//! "family". Some prominent examples (note that each of these modules
//! has their own README with further details).
//!
//! - **HIR.** The "high-level (H) intermediate representation (IR)" is
//!   defined in the `hir` module.
//! - **MIR.** The "mid-level (M) intermediate representation (IR)" is
//!   defined in the `mir` module. This module contains only the
//!   *definition* of the MIR; the passes that transform and operate
//!   on MIR are found in `rustc_mir` crate.
//! - **Types.** The internal representation of types used in rustc is
//!   defined in the `ty` module. This includes the **type context**
//!   (or `tcx`), which is the central context during most of
//!   compilation, containing the interners and other things.
//!
//! For more information about how rustc works, see the [rustc dev guide].
//!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/
//!
//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(array_windows)]
#![feature(assoc_char_funcs)]
#![feature(backtrace)]
#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(cmp_min_max_by)]
#![feature(const_fn)]
#![feature(const_panic)]
#![feature(core_intrinsics)]
#![feature(discriminant_kind)]
#![feature(never_type)]
#![feature(extern_types)]
#![feature(nll)]
#![feature(once_cell)]
#![feature(option_expect_none)]
#![feature(or_patterns)]
#![feature(min_specialization)]
#![feature(trusted_len)]
#![feature(test)]
#![feature(in_band_lifetimes)]
#![feature(crate_visibility_modifier)]
#![feature(associated_type_bounds)]
#![feature(rustc_attrs)]
#![feature(int_error_matching)]
#![feature(half_open_range_patterns)]
#![feature(exclusive_range_pattern)]
#![feature(control_flow_enum)]
#![feature(associated_type_defaults)]
#![recursion_limit = "512"]

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate rustc_macros;
#[macro_use]
extern crate rustc_data_structures;
#[macro_use]
extern crate tracing;
#[macro_use]
extern crate smallvec;

#[cfg(test)]
mod tests;

#[macro_use]
mod macros;

#[macro_use]
pub mod query;

#[macro_use]
pub mod arena;
pub mod dep_graph;
pub mod hir;
pub mod ich;
pub mod infer;
pub mod lint;
pub mod middle;
pub mod mir;
pub mod traits;
pub mod ty;

pub mod util {
    pub mod bug;
    pub mod common;
}

// Allows macros to refer to this crate as `::rustc_middle`
extern crate self as rustc_middle;
<|endoftext|>


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

use std::path::Path;

use filesystem;
use users;

use error::{Error, Result};

pub fn set_owner<T: AsRef<Path>, X: AsRef<str>>(path: T, owner: X, group: X) -> Result<()> {
    debug!(
        "Attempting to set owner of {:?} to {:?}",
        &path.as_ref(),
        &owner.as_ref()
    );

    let uid = match users::get_uid_by_name(&owner.as_ref()) {
        Some(user) => user,
        None => {
            let msg = format!(
                "Can't change owner of {:?} to {:?}:{:?}, error getting user.",
                &path.as_ref(),
                &owner.as_ref(),
                &group.as_ref()
            );
            return Err(Error::PermissionFailed(msg));
        }
    };

    let gid = match users::get_gid_by_name(&group.as_ref()) {
        Some(group) => group,
        None => {
            let msg = format!(
                "Can't change owner of {:?} to {:?}:{:?}, error getting group.",
                &path.as_ref(),
                &owner.as_ref(),
                &group.as_ref()
            );
            return Err(Error::PermissionFailed(msg));
        }
    };

    let s_path = match path.as_ref().to_str() {
        Some(s) => s,
        None => {
            return Err(Error::PermissionFailed(
                format!("Invalid path {:?}", &path.as_ref()),
            ))
        }

    };
    let result = filesystem::chown(s_path, uid, gid);

    match result {
        Err(err) => Err(err),
        Ok(0) => Ok(()),
        _ => {
            Err(Error::PermissionFailed(format!(
                "Can't change owner of {:?} to {:?}",
                &path.as_ref(),
                &owner.as_ref()
            )))
        }
    }
}

pub fn set_permissions<T: AsRef<Path>>(path: T, mode: u32) -> Result<()> {
    let s_path = match path.as_ref().to_str() {
        Some(s) => s,
        None => {
            return Err(Error::PermissionFailed(
                format!("Invalid path {:?}", &path.as_ref()),
            ))
        }

    };

    let result = filesystem::chmod(s_path, mode);
    match result {
        Err(err) => Err(err),
        Ok(0) => Ok(()),
        _ => {
            Err(Error::PermissionFailed(format!(
                "Can't set permissions on {:?} to {:?}",
                &path.as_ref(),
                &mode
            )))
        }
    }
}

#[cfg(test)]
mod tests {
    use std::fs::File;
    use std::io::Write;
    use std::path::Path;

    use tempdir::TempDir;

    use error::Error;
    use super::*;

    #[test]
    fn chmod_ok_test() {
        let tmp_dir = TempDir::new("foo").expect("create temp dir");
        let file_path = tmp_dir.path().join("test.txt");
        let mut tmp_file = File::create(&file_path).expect("create temp file");
        writeln!(tmp_file, "foobar123").expect("write temp file");

        let mode = 0o745;
        assert!(set_permissions(file_path, mode).is_ok());
        drop(tmp_file);
        tmp_dir.close().expect("delete temp dir");
    }

    #[test]
    fn chmod_fail_test() {
        let mode = 0o745;
        let badpath = Path::new("this_file_should_never_exist_deadbeef");
        if let Err(Error::PermissionFailed(_)) = set_permissions(badpath, mode) {
            assert!(true);
        } else {
            assert!(false);
        }
    }
}
<commit_msg>[core] Show group in debug when calling `util::perm::set_owner()`.<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::path::Path;

use filesystem;
use users;

use error::{Error, Result};

pub fn set_owner<T: AsRef<Path>, X: AsRef<str>>(path: T, owner: X, group: X) -> Result<()> {
    debug!(
        "Attempting to set owner of {:?} to {:?}:{:?}",
        &path.as_ref(),
        &owner.as_ref(),
        &group.as_ref()
    );

    let uid = match users::get_uid_by_name(&owner.as_ref()) {
        Some(user) => user,
        None => {
            let msg = format!(
                "Can't change owner of {:?} to {:?}:{:?}, error getting user.",
                &path.as_ref(),
                &owner.as_ref(),
                &group.as_ref()
            );
            return Err(Error::PermissionFailed(msg));
        }
    };

    let gid = match users::get_gid_by_name(&group.as_ref()) {
        Some(group) => group,
        None => {
            let msg = format!(
                "Can't change owner of {:?} to {:?}:{:?}, error getting group.",
                &path.as_ref(),
                &owner.as_ref(),
                &group.as_ref()
            );
            return Err(Error::PermissionFailed(msg));
        }
    };

    let s_path = match path.as_ref().to_str() {
        Some(s) => s,
        None => {
            return Err(Error::PermissionFailed(
                format!("Invalid path {:?}", &path.as_ref()),
            ))
        }

    };
    let result = filesystem::chown(s_path, uid, gid);

    match result {
        Err(err) => Err(err),
        Ok(0) => Ok(()),
        _ => {
            Err(Error::PermissionFailed(format!(
                "Can't change owner of {:?} to {:?}:{:?}",
                &path.as_ref(),
                &owner.as_ref(),
                &group.as_ref()
            )))
        }
    }
}

pub fn set_permissions<T: AsRef<Path>>(path: T, mode: u32) -> Result<()> {
    let s_path = match path.as_ref().to_str() {
        Some(s) => s,
        None => {
            return Err(Error::PermissionFailed(
                format!("Invalid path {:?}", &path.as_ref()),
            ))
        }

    };

    let result = filesystem::chmod(s_path, mode);
    match result {
        Err(err) => Err(err),
        Ok(0) => Ok(()),
        _ => {
            Err(Error::PermissionFailed(format!(
                "Can't set permissions on {:?} to {:?}",
                &path.as_ref(),
                &mode
            )))
        }
    }
}

#[cfg(test)]
mod tests {
    use std::fs::File;
    use std::io::Write;
    use std::path::Path;

    use tempdir::TempDir;

    use error::Error;
    use super::*;

    #[test]
    fn chmod_ok_test() {
        let tmp_dir = TempDir::new("foo").expect("create temp dir");
        let file_path = tmp_dir.path().join("test.txt");
        let mut tmp_file = File::create(&file_path).expect("create temp file");
        writeln!(tmp_file, "foobar123").expect("write temp file");

        let mode = 0o745;
        assert!(set_permissions(file_path, mode).is_ok());
        drop(tmp_file);
        tmp_dir.close().expect("delete temp dir");
    }

    #[test]
    fn chmod_fail_test() {
        let mode = 0o745;
        let badpath = Path::new("this_file_should_never_exist_deadbeef");
        if let Err(Error::PermissionFailed(_)) = set_permissions(badpath, mode) {
            assert!(true);
        } else {
            assert!(false);
        }
    }
}
<|endoftext|>


<commit_before>use std::{cmp, fmt};

pub struct Clock {
    hours: u8,
    minutes: u8,
}

impl Clock {
    pub fn new(hours: i32, minutes: i32) -> Self {
        unimplemented!(
            "Construct a new Clock from {} hours and {} minutes",
            hours,
            minutes
        );
    }

    pub fn add_minutes(self, minutes: i32) -> Self {
        unimplemented!("Add {} minutes to existing Clock time", minutes);
    }

    pub fn to_string(&self) -> String {
        unimplemented!("Return String representation of a Clock");
    }
}

impl fmt::Debug for Clock {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unimplemented!("Return debug representation of a Clock");
    }
}

impl cmp::PartialEq for Clock {
    fn eq(&self, other: &Clock) -> bool {
        unimplemented!("Implement comparison between two Clocks");
    }
}
<commit_msg>Silenced unused variables warnings<commit_after>use std::{cmp, fmt};

pub struct Clock {
    hours: u8,
    minutes: u8,
}

impl Clock {
    pub fn new(hours: i32, minutes: i32) -> Self {
        unimplemented!(
            "Construct a new Clock from {} hours and {} minutes",
            hours,
            minutes
        );
    }

    pub fn add_minutes(self, minutes: i32) -> Self {
        unimplemented!("Add {} minutes to existing Clock time", minutes);
    }

    pub fn to_string(&self) -> String {
        unimplemented!("Return String representation of a Clock");
    }
}

impl fmt::Debug for Clock {
    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
        unimplemented!("Return debug representation of a Clock");
    }
}

impl cmp::PartialEq for Clock {
    fn eq(&self, _other: &Clock) -> bool {
        unimplemented!("Implement comparison between two Clocks");
    }
}
<|endoftext|>


<commit_before>use byteorder::{ByteOrder, BigEndian};
use crypto::{Hash, PublicKey, HASH_SIZE, PUBLIC_KEY_LENGTH};

pub trait StorageKey {
    fn size(&self) -> usize;
    fn write(&self, buffer: &mut [u8]);
    fn read(buffer: &[u8]) -> Self;
}

impl StorageKey for () {
    fn size(&self) -> usize {
        0
    }

    fn write(&self, _buffer: &mut [u8]) {
        // no-op
    }

    fn read(_buffer: &[u8]) -> Self {
        ()
    }
}

impl StorageKey for u8 {
    fn size(&self) -> usize {
        1
    }

    fn write(&self, buffer: &mut [u8]) {
        buffer[0] = *self
    }

    fn read(buffer: &[u8]) -> Self {
        buffer[0]
    }
}

impl StorageKey for u16 {
    fn size(&self) -> usize {
        2
    }

    fn write(&self, buffer: &mut [u8]) {
        BigEndian::write_u16(buffer, *self)
    }

    fn read(buffer: &[u8]) -> Self {
        BigEndian::read_u16(buffer)
    }
}

impl StorageKey for u32 {
    fn size(&self) -> usize {
        4
    }

    fn write(&self, buffer: &mut [u8]) {
        BigEndian::write_u32(buffer, *self)
    }

    fn read(buffer: &[u8]) -> Self {
        BigEndian::read_u32(buffer)
    }
}

impl StorageKey for u64 {
    fn size(&self) -> usize {
        8
    }

    fn write(&self, buffer: &mut [u8]) {
        BigEndian::write_u64(buffer, *self)
    }

    fn read(buffer: &[u8]) -> Self {
        BigEndian::read_u64(buffer)
    }
}

impl StorageKey for i8 {
    fn size(&self) -> usize {
        1
    }

    fn write(&self, buffer: &mut [u8]) {
        buffer[0] = *self as u8
    }

    fn read(buffer: &[u8]) -> Self {
        buffer[0] as i8
    }
}

impl StorageKey for i16 {
    fn size(&self) -> usize {
        2
    }

    fn write(&self, buffer: &mut [u8]) {
        BigEndian::write_i16(buffer, *self)
    }

    fn read(buffer: &[u8]) -> Self {
        BigEndian::read_i16(buffer)
    }
}

impl StorageKey for i32 {
    fn size(&self) -> usize {
        4
    }

    fn write(&self, buffer: &mut [u8]) {
        BigEndian::write_i32(buffer, *self)
    }

    fn read(buffer: &[u8]) -> Self {
        BigEndian::read_i32(buffer)
    }
}

impl StorageKey for i64 {
    fn size(&self) -> usize {
        8
    }

    fn write(&self, buffer: &mut [u8]) {
        BigEndian::write_i64(buffer, *self)
    }

    fn read(buffer: &[u8]) -> Self {
        BigEndian::read_i64(buffer)
    }
}

impl StorageKey for Hash {
    fn size(&self) -> usize {
        HASH_SIZE
    }

    fn write(&self, buffer: &mut [u8]) {
        buffer.copy_from_slice(self.as_ref())
    }

    fn read(buffer: &[u8]) -> Self {
        Hash::from_slice(buffer).unwrap()
    }
}

impl StorageKey for PublicKey {
    fn size(&self) -> usize {
        PUBLIC_KEY_LENGTH
    }

    fn write(&self, buffer: &mut [u8]) {
        buffer.copy_from_slice(self.as_ref())
    }

    fn read(buffer: &[u8]) -> Self {
        PublicKey::from_slice(buffer).unwrap()
    }
}

impl StorageKey for Vec<u8> {
    fn size(&self) -> usize {
        self.len()
    }

    fn write(&self, buffer: &mut [u8]) {
        buffer.copy_from_slice(&self)
    }

    fn read(buffer: &[u8]) -> Self {
        buffer.to_vec()
    }
}
<commit_msg>Impl StorageKey for String<commit_after>use byteorder::{ByteOrder, BigEndian};
use crypto::{Hash, PublicKey, HASH_SIZE, PUBLIC_KEY_LENGTH};

pub trait StorageKey {
    fn size(&self) -> usize;
    fn write(&self, buffer: &mut [u8]);
    fn read(buffer: &[u8]) -> Self;
}

impl StorageKey for () {
    fn size(&self) -> usize {
        0
    }

    fn write(&self, _buffer: &mut [u8]) {
        // no-op
    }

    fn read(_buffer: &[u8]) -> Self {
        ()
    }
}

impl StorageKey for u8 {
    fn size(&self) -> usize {
        1
    }

    fn write(&self, buffer: &mut [u8]) {
        buffer[0] = *self
    }

    fn read(buffer: &[u8]) -> Self {
        buffer[0]
    }
}

impl StorageKey for u16 {
    fn size(&self) -> usize {
        2
    }

    fn write(&self, buffer: &mut [u8]) {
        BigEndian::write_u16(buffer, *self)
    }

    fn read(buffer: &[u8]) -> Self {
        BigEndian::read_u16(buffer)
    }
}

impl StorageKey for u32 {
    fn size(&self) -> usize {
        4
    }

    fn write(&self, buffer: &mut [u8]) {
        BigEndian::write_u32(buffer, *self)
    }

    fn read(buffer: &[u8]) -> Self {
        BigEndian::read_u32(buffer)
    }
}

impl StorageKey for u64 {
    fn size(&self) -> usize {
        8
    }

    fn write(&self, buffer: &mut [u8]) {
        BigEndian::write_u64(buffer, *self)
    }

    fn read(buffer: &[u8]) -> Self {
        BigEndian::read_u64(buffer)
    }
}

impl StorageKey for i8 {
    fn size(&self) -> usize {
        1
    }

    fn write(&self, buffer: &mut [u8]) {
        buffer[0] = *self as u8
    }

    fn read(buffer: &[u8]) -> Self {
        buffer[0] as i8
    }
}

impl StorageKey for i16 {
    fn size(&self) -> usize {
        2
    }

    fn write(&self, buffer: &mut [u8]) {
        BigEndian::write_i16(buffer, *self)
    }

    fn read(buffer: &[u8]) -> Self {
        BigEndian::read_i16(buffer)
    }
}

impl StorageKey for i32 {
    fn size(&self) -> usize {
        4
    }

    fn write(&self, buffer: &mut [u8]) {
        BigEndian::write_i32(buffer, *self)
    }

    fn read(buffer: &[u8]) -> Self {
        BigEndian::read_i32(buffer)
    }
}

impl StorageKey for i64 {
    fn size(&self) -> usize {
        8
    }

    fn write(&self, buffer: &mut [u8]) {
        BigEndian::write_i64(buffer, *self)
    }

    fn read(buffer: &[u8]) -> Self {
        BigEndian::read_i64(buffer)
    }
}

impl StorageKey for Hash {
    fn size(&self) -> usize {
        HASH_SIZE
    }

    fn write(&self, buffer: &mut [u8]) {
        buffer.copy_from_slice(self.as_ref())
    }

    fn read(buffer: &[u8]) -> Self {
        Hash::from_slice(buffer).unwrap()
    }
}

impl StorageKey for PublicKey {
    fn size(&self) -> usize {
        PUBLIC_KEY_LENGTH
    }

    fn write(&self, buffer: &mut [u8]) {
        buffer.copy_from_slice(self.as_ref())
    }

    fn read(buffer: &[u8]) -> Self {
        PublicKey::from_slice(buffer).unwrap()
    }
}

impl StorageKey for Vec<u8> {
    fn size(&self) -> usize {
        self.len()
    }

    fn write(&self, buffer: &mut [u8]) {
        buffer.copy_from_slice(&self)
    }

    fn read(buffer: &[u8]) -> Self {
        buffer.to_vec()
    }
}

impl StorageKey for String {
    fn size(&self) -> usize {
        self.len()
    }

    fn write(&self, buffer: &mut [u8]) {
        buffer.copy_from_slice(self.as_bytes())
    }

    fn read(buffer: &[u8]) -> Self {
        unsafe { ::std::str::from_utf8_unchecked(buffer).to_string() }
    }
}
<|endoftext|>