use std::any::TypeId;
use std::cell::RefCell;
use std::mem;
use std::fmt::{self, Debug};
pub struct DebugIterableOpaque<I> {
one_use_inner: RefCell<I>
}
impl<I> DebugIterableOpaque<I> {
pub fn new(one_use_inner: I) -> Self {
let one_use_inner = RefCell::new(one_use_inner);
DebugIterableOpaque { one_use_inner }
}
}
impl<I> Debug for DebugIterableOpaque<I>
where I: Iterator, I::Item: Debug
{
fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result {
let mut borrow = self.one_use_inner.borrow_mut();
fter.debug_list().entries(&mut *borrow).finish()
}
}
#[inline(always)]
pub fn uneraser_ref<GOT: 'static, EXP: 'static>(inp: &GOT ) -> Option<&EXP> {
if TypeId::of::<GOT>() == TypeId::of::<EXP>() {
let res: &EXP = unsafe { mem::transmute::<&GOT, &EXP>(inp) };
Some( res )
} else {
None
}
}
#[doc(hidden)]
#[inline(always)]
pub fn uneraser_mut<GOT: 'static, EXP: 'static>(inp: &mut GOT ) -> Option<&mut EXP> {
if TypeId::of::<GOT>() == TypeId::of::<EXP>() {
let res: &mut EXP = unsafe { mem::transmute::<&mut GOT, &mut EXP>(inp) };
Some( res )
} else {
None
}
}
pub fn is_utf8_continuation_byte(b: u8) -> bool {
(b & 0b11000000) == 0b10000000
}
pub fn vec_insert_bytes(target: &mut Vec<u8>, idx: usize, source: &[u8]) {
use std::ptr::copy;
if idx > target.len() {
panic!("index out of bounds: the len is {} but the index is {}",
target.len(), idx);
}
let old_len = target.len();
let insertion_len = source.len();
let source_ptr = source.as_ptr();
let insertion_point = unsafe {
target.as_mut_ptr().offset(idx as isize)
};
let moved_data_len = old_len - idx;
target.reserve(insertion_len);
unsafe {
copy(insertion_point,
insertion_point.offset(insertion_len as isize),
moved_data_len);
copy(source_ptr, insertion_point, insertion_len);
target.set_len(old_len + insertion_len)
}
}
#[cfg(test)]
mod tests {
use super::vec_insert_bytes;
#[test]
fn inserting_slices_at_beginning() {
let mut base = vec![0u8, 1u8, 2u8, 3u8];
let new = &[10u8, 11];
vec_insert_bytes(&mut base, 0, new);
assert_eq!(&*base, &[10u8, 11, 0, 1, 2, 3]);
assert!(base.capacity() >= 6);
}
#[test]
fn inserting_slices_at_end() {
let mut base = vec![0u8, 1u8, 2u8, 3u8];
let new = &[10u8, 11];
let end = base.len();
vec_insert_bytes(&mut base, end, new);
assert_eq!(&*base, &[0u8, 1, 2, 3, 10, 11]);
assert!(base.capacity() >= 6);
}
#[test]
fn inserting_slices_in_the_middle() {
let mut base = vec![0u8, 1u8, 2u8, 3u8];
let new = &[10u8, 11];
vec_insert_bytes(&mut base, 1, new);
assert_eq!(&*base, &[0u8, 10, 11, 1, 2, 3]);
assert!(base.capacity() >= 6);
}
#[test]
fn inserting_slices_large_in_the_middle() {
let mut base = vec![0u8, 1u8, 2u8, 3u8];
let new = &[10u8, 11, 12, 13, 14, 15, 16];
vec_insert_bytes(&mut base, 1, new);
assert_eq!(&*base, &[0u8, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3]);
assert!(base.capacity() >= 11);
}
#[should_panic]
#[test]
fn insert_out_of_bound() {
let mut base = vec![0u8, 1u8, 2u8, 3u8];
let new = &[10u8];
vec_insert_bytes(&mut base, 10, new);
}
}