diff options
Diffstat (limited to 'vendor/im-rc/src/util.rs')
-rw-r--r-- | vendor/im-rc/src/util.rs | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/vendor/im-rc/src/util.rs b/vendor/im-rc/src/util.rs new file mode 100644 index 000000000..5451f156d --- /dev/null +++ b/vendor/im-rc/src/util.rs @@ -0,0 +1,142 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// Every codebase needs a `util` module. + +use std::cmp::Ordering; +use std::ops::{Bound, IndexMut, Range, RangeBounds}; +use std::ptr; + +#[cfg(feature = "pool")] +pub(crate) use refpool::{PoolClone, PoolDefault}; + +// The `Ref` type is an alias for either `Rc` or `Arc`, user's choice. + +// `Arc` without refpool +#[cfg(all(threadsafe))] +pub(crate) use crate::fakepool::{Arc as PoolRef, Pool, PoolClone, PoolDefault}; + +// `Ref` == `Arc` when threadsafe +#[cfg(threadsafe)] +pub(crate) type Ref<A> = std::sync::Arc<A>; + +// `Rc` without refpool +#[cfg(all(not(threadsafe), not(feature = "pool")))] +pub(crate) use crate::fakepool::{Pool, PoolClone, PoolDefault, Rc as PoolRef}; + +// `Rc` with refpool +#[cfg(all(not(threadsafe), feature = "pool"))] +pub(crate) type PoolRef<A> = refpool::PoolRef<A>; +#[cfg(all(not(threadsafe), feature = "pool"))] +pub(crate) type Pool<A> = refpool::Pool<A>; + +// `Ref` == `Rc` when not threadsafe +#[cfg(not(threadsafe))] +pub(crate) type Ref<A> = std::rc::Rc<A>; + +pub(crate) fn clone_ref<A>(r: Ref<A>) -> A +where + A: Clone, +{ + Ref::try_unwrap(r).unwrap_or_else(|r| (*r).clone()) +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub(crate) enum Side { + Left, + Right, +} + +/// Swap two values of anything implementing `IndexMut`. +/// +/// Like `slice::swap`, but more generic. +#[allow(unsafe_code)] +pub(crate) fn swap_indices<V>(vector: &mut V, a: usize, b: usize) +where + V: IndexMut<usize>, + V::Output: Sized, +{ + if a == b { + return; + } + // so sorry, but there's no implementation for this in std that's + // sufficiently generic + let pa: *mut V::Output = &mut vector[a]; + let pb: *mut V::Output = &mut vector[b]; + unsafe { + ptr::swap(pa, pb); + } +} + +#[allow(dead_code)] +pub(crate) fn linear_search_by<'a, A, I, F>(iterable: I, mut cmp: F) -> Result<usize, usize> +where + A: 'a, + I: IntoIterator<Item = &'a A>, + F: FnMut(&A) -> Ordering, +{ + let mut pos = 0; + for value in iterable { + match cmp(value) { + Ordering::Equal => return Ok(pos), + Ordering::Greater => return Err(pos), + Ordering::Less => {} + } + pos += 1; + } + Err(pos) +} + +pub(crate) fn to_range<R>(range: &R, right_unbounded: usize) -> Range<usize> +where + R: RangeBounds<usize>, +{ + let start_index = match range.start_bound() { + Bound::Included(i) => *i, + Bound::Excluded(i) => *i + 1, + Bound::Unbounded => 0, + }; + let end_index = match range.end_bound() { + Bound::Included(i) => *i + 1, + Bound::Excluded(i) => *i, + Bound::Unbounded => right_unbounded, + }; + start_index..end_index +} + +macro_rules! def_pool { + ($name:ident<$($arg:tt),*>, $pooltype:ty) => { + /// A memory pool for the appropriate node type. + pub struct $name<$($arg,)*>(Pool<$pooltype>); + + impl<$($arg,)*> $name<$($arg,)*> { + /// Create a new pool with the given size. + pub fn new(size: usize) -> Self { + Self(Pool::new(size)) + } + + /// Fill the pool with preallocated chunks. + pub fn fill(&self) { + self.0.fill(); + } + + ///Get the current size of the pool. + pub fn pool_size(&self) -> usize { + self.0.get_pool_size() + } + } + + impl<$($arg,)*> Default for $name<$($arg,)*> { + fn default() -> Self { + Self::new($crate::config::POOL_SIZE) + } + } + + impl<$($arg,)*> Clone for $name<$($arg,)*> { + fn clone(&self) -> Self { + Self(self.0.clone()) + } + } + }; +} |