use core::borrow::Borrow; use core::cmp::Ordering; use super::node::{marker, ForceResult::*, Handle, NodeRef}; use SearchResult::*; pub enum SearchResult { Found(Handle, marker::KV>), GoDown(Handle, marker::Edge>), } /// Looks up a given key in a (sub)tree headed by the given node, recursively. /// Returns a `Found` with the handle of the matching KV, if any. Otherwise, /// returns a `GoDown` with the handle of the possible leaf edge where the key /// belongs. pub fn search_tree( mut node: NodeRef, key: &Q, ) -> SearchResult where Q: Ord, K: Borrow, { loop { match search_node(node, key) { Found(handle) => return Found(handle), GoDown(handle) => match handle.force() { Leaf(leaf) => return GoDown(leaf), Internal(internal) => { node = internal.descend(); continue; } }, } } } /// Looks up a given key in a given node, without recursion. /// Returns a `Found` with the handle of the matching KV, if any. Otherwise, /// returns a `GoDown` with the handle of the edge where the key might be found. /// If the node is a leaf, a `GoDown` edge is not an actual edge but a possible edge. pub fn search_node( node: NodeRef, key: &Q, ) -> SearchResult where Q: Ord, K: Borrow, { match search_linear(&node, key) { (idx, true) => Found(unsafe { Handle::new_kv(node, idx) }), (idx, false) => SearchResult::GoDown(unsafe { Handle::new_edge(node, idx) }), } } /// Returns the index in the node at which the key (or an equivalent) exists /// or could exist, and whether it exists in the node itself. If it doesn't /// exist in the node itself, it may exist in the subtree with that index /// (if the node has subtrees). If the key doesn't exist in node or subtree, /// the returned index is the position or subtree where the key belongs. fn search_linear( node: &NodeRef, key: &Q, ) -> (usize, bool) where Q: Ord, K: Borrow, { // This function is defined over all borrow types (immutable, mutable, owned). // Using `keys()` is fine here even if BorrowType is mutable, as all we return // is an index -- not a reference. let len = node.len(); let keys = node.keys(); for (i, k) in keys.iter().enumerate() { match key.cmp(k.borrow()) { Ordering::Greater => {} Ordering::Equal => return (i, true), Ordering::Less => return (i, false), } } (len, false) }