You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
videl/src/util.rs

143 lines
2.9 KiB

//! Utility functions
use std::{
borrow::{
Borrow,
ToOwned,
},
};
/// Copy slice `src` into `dst` and return the number of elements copied.
#[inline] pub fn copy_slice<T,U,V,W,X>(mut dst: V, src: W) -> usize
where V: AsMut<[T]>,
W: AsRef<[U]>,
U: ToOwned<Owned=X>,
X: Borrow<U> + Into<T>
{
let mut i=0;
for (d, s) in dst.as_mut().iter_mut().zip(src.as_ref().iter())
{
*d = s.to_owned().into();
i+=1
}
i
}
pub mod bytes
{
/// Copy `src`'s bytes into `dst`, returning the number of bytes copied.
///
/// # Note
/// The memory regions must not overlap
pub fn copy_slice(dst: &mut [u8], src: &[u8]) -> usize
{
let sz = std::cmp::min(dst.len(), src.len());
if sz != 0 {
unsafe {
std::ptr::copy_nonoverlapping(&src[0] as *const u8, &mut dst[0] as *mut u8, sz);
}
}
sz
}
/// Copy `src`'s bytes into `dst`, returning the number of bytes copied.
///
/// # Note
/// The memory regions can overlap
pub fn move_slice(dst: &mut [u8], src: &[u8]) -> usize
{
let sz = std::cmp::min(dst.len(), src.len());
if sz != 0 {
unsafe {
std::ptr::copy(&src[0] as *const u8, &mut dst[0] as *mut u8, sz);
}
}
sz
}
}
#[cfg(test)]
mod tests
{
#[test]
fn copy_slice()
{
let mut to = [0u8; 40];
let from = [10u8; 37];
assert_eq!(super::copy_slice(&mut to, &from), 37);
assert_eq!(from, &to[0..37]);
}
}
pub trait NewWithCap: Sized
{
fn new() -> Self;
fn with_capacity(cap: usize) -> Self;
}
impl<T> NewWithCap for Vec<T>
{
#[inline(always)] fn new() -> Self
{
Self::new()
}
#[inline(always)] fn with_capacity(cap: usize) -> Self
{
Self::with_capacity(cap)
}
}
impl NewWithCap for String
{
#[inline(always)] fn new() -> Self
{
Self::new()
}
#[inline(always)] fn with_capacity(cap: usize) -> Self
{
Self::with_capacity(cap)
}
}
/// Allocate with capacity based on iterator `size_hint`
#[inline] pub fn alloc_iterator_hint<T: NewWithCap, I: Iterator+?Sized>(hint: &I) -> T
{
match hint.size_hint() {
(0, None) | (_, Some(0)) => T::new(),
(_, Some(x)) | (x, None) => T::with_capacity(x),
}
}
/// Allocate with capacity based on stream `size_hint`
#[inline] pub fn alloc_stream_hint<T: NewWithCap, I: futures::stream::Stream+?Sized>(hint: &I) -> T
{
match hint.size_hint() {
(0, None) | (_, Some(0)) => T::new(),
(_, Some(x)) | (x, None) => T::with_capacity(x),
}
}
/// Defer an action until drop
pub fn defer<F: FnOnce()>(fun: F) -> impl std::ops::Drop
{
struct DropWrap<F: FnOnce()>(Option<F>);
impl<F: FnOnce()> std::ops::Drop for DropWrap<F>
{
fn drop(&mut self)
{
self.0.take().map(|x| x());
}
}
DropWrap(Some(fun))
}
/// Simplification for single expression `if x {y} else {z}`
#[macro_export] macro_rules! tern {
($if:expr; $then:expr, $else:expr) => (if $if {$then} else {$else});
}