ipmb 0.8.5

Inter-process message bus
Documentation
use rand::Rng;
use serde::{Deserialize, Serialize};
use std::ops::{Bound, RangeBounds};
use type_uuid::Bytes;

#[allow(dead_code)]
pub fn vec_take<T, F: FnMut(&mut T) -> bool>(source: &mut Vec<T>, receiver: &mut Vec<T>, mut f: F) {
    let mut i = 0;
    while i < source.len() {
        if f(&mut source[i]) {
            let val = source.swap_remove(i);
            receiver.push(val);
        } else {
            i += 1;
        }
    }
}

pub trait Align4 {
    fn align4(self) -> Self;
}

impl Align4 for usize {
    #[inline]
    fn align4(mut self) -> Self {
        if (self & 0x3) != 0 {
            self = (self & !0x3) + 4;
        }
        self
    }
}

impl Align4 for u32 {
    #[inline]
    fn align4(mut self) -> Self {
        if (self & 0x3) != 0 {
            self = (self & !0x3) + 4;
        }
        self
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct EndpointID(Bytes);

impl EndpointID {
    pub fn new() -> Self {
        Self(uuid::Uuid::new_v4().into_bytes())
    }
}

#[allow(dead_code)]
pub fn rand_string(length: usize) -> String {
    rand::thread_rng()
        .sample_iter(&rand::distributions::Alphanumeric)
        .take(length)
        .map(char::from)
        .collect()
}

pub fn range_to_offset_size<S: RangeBounds<usize>>(bounds: S) -> (usize, Option<usize>) {
    let offset = match bounds.start_bound() {
        Bound::Included(&bound) => bound,
        Bound::Excluded(&bound) => bound + 1,
        Bound::Unbounded => 0,
    };
    let size = match bounds.end_bound() {
        Bound::Included(&bound) => Some(bound + 1 - offset),
        Bound::Excluded(&bound) => Some(bound - offset),
        Bound::Unbounded => None,
    };

    (offset, size)
}