-
Georgy Moshkin authoredGeorgy Moshkin authored
utils.rs 4.51 KiB
use std::cell::{RefCell, RefMut};
use std::collections::HashMap;
use std::hash::{BuildHasher, Hash, RandomState};
use std::io::{Result, Write};
use std::ops::DerefMut;
use rmp::encode::RmpWrite;
use rmp::Marker;
use tarantool::fiber::mutex::MutexGuard as TMutexGuard;
use tarantool::fiber::Mutex as TMutex;
/// [`MutexLike`] is a mutex abstraction to work with different mutexes in general manner.
///
/// It is needed as sometimes we are unable to use tarantool's [`TMutex`].
/// For instance, if we run ordinary Rust unit tests, tarantool symbols would be missing.
pub trait MutexLike<T> {
type Guard<'a>: DerefMut<Target = T>
where
Self: 'a,
T: 'a;
fn lock(&self) -> Self::Guard<'_>;
}
impl<T> MutexLike<T> for TMutex<T> {
type Guard<'a>
= TMutexGuard<'a, T>
where
T: 'a;
fn lock(&self) -> Self::Guard<'_> {
self.lock()
}
}
impl<T> MutexLike<T> for RefCell<T> {
type Guard<'a>
= RefMut<'a, T>
where
T: 'a;
fn lock(&self) -> Self::Guard<'_> {
self.borrow_mut()
}
}
#[derive(Debug, Default)]
pub struct ByteCounter(usize);
impl ByteCounter {
#[must_use]
pub fn bytes(&self) -> usize {
self.0
}
}
impl Write for ByteCounter {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.0 += buf.len();
Ok(buf.len())
}
fn flush(&mut self) -> Result<()> {
Ok(())
}
}
pub fn write_u32_array_len<W: Write>(stream: &mut W, len: u32) -> Result<()> {
stream.write_bytes(&[Marker::Array32.to_u8()])?;
let mut buf = [0u8; 4];
buf.copy_from_slice(&len.to_be_bytes());
stream.write_bytes(&buf)?;
Ok(())
}
pub struct OrderedMap<K, V, S = RandomState> {
map: HashMap<K, V, S>,
order: Vec<(K, V)>,
}
pub struct OrderedMapIterator<'map, K, V, S> {
map: &'map OrderedMap<K, V, S>,
index: usize,
}
impl<'map, K: Clone + Hash + Eq, V: Clone, S: BuildHasher> OrderedMapIterator<'map, K, V, S> {
fn new(map: &'map OrderedMap<K, V, S>) -> Self {
Self { map, index: 0 }
}
}
impl<'map, K: Clone + Hash + Eq, V: Clone, S: BuildHasher> Iterator
for OrderedMapIterator<'map, K, V, S>
{
type Item = &'map (K, V);
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.map.len() {
let res = &self.map.order[self.index];
self.index += 1;
Some(res)
} else {
None
}
}
}
impl<K: Clone + Hash + Eq, V: Clone, S: BuildHasher> OrderedMap<K, V, S> {
pub fn with_hasher(hasher: S) -> Self {
Self {
map: HashMap::<K, V, S>::with_hasher(hasher),
order: Vec::<(K, V)>::new(),
}
}
pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
Self {
map: HashMap::<K, V, S>::with_capacity_and_hasher(capacity, hasher),
order: Vec::<(K, V)>::new(),
}
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn get(&self, key: &K) -> Option<&V> {
self.map.get(key)
}
pub fn remove(&mut self, key: &K) -> Option<V> {
self.order.retain(|(k, _)| k != key);
self.map.remove(key)
}
pub fn insert(&mut self, key: K, value: V) {
if self.map.insert(key.clone(), value.clone()).is_none() {
self.order.push((key, value));
}
}
pub fn iter(&self) -> OrderedMapIterator<K, V, S> {
OrderedMapIterator::new(self)
}
}
pub struct OrderedSet<V, S = RandomState> {
map: OrderedMap<V, (), S>,
}
pub struct OrderedSetIterator<'set, V, S> {
map_iterator: OrderedMapIterator<'set, V, (), S>,
}
impl<'set, V: Clone + Hash + Eq, S: BuildHasher> Iterator for OrderedSetIterator<'set, V, S> {
type Item = &'set V;
fn next(&mut self) -> Option<Self::Item> {
self.map_iterator.next().map(|(k, _)| k)
}
}
impl<V: Clone + Hash + Eq, S: BuildHasher> OrderedSet<V, S> {
pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
Self {
map: OrderedMap::<V, (), S>::with_capacity_and_hasher(capacity, hasher),
}
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn insert(&mut self, value: V) {
self.map.insert(value, ())
}
pub fn iter(&self) -> OrderedSetIterator<V, S> {
OrderedSetIterator {
map_iterator: OrderedMapIterator::new(&self.map),
}
}
}