1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//! This crate provides Go style copying / cloning for slices.
//!
//! For times when you do not want to worry about slices being unequal sizes, this crate is here
//! for you.
//!
//! # Examples
//! 
//! We can use `copy` for types that implement `Copy`.
//!
//! ```
//! use slice_copy::copy;
//! 
//! let mut l = b"hello".to_vec();
//! let r = b"goodbye".to_vec();
//!
//! let n = copy(&mut l, &r);
//!
//! assert_eq!(n, 5);
//! assert_eq!(l, b"goodb");
//! ```
//!
//! `u8`s are special cased for if either side is short.
//!
//! ```
//! use slice_copy::u8s_copy;
//! 
//! let mut l = vec![1 as u8, 2, 3];
//! let r = vec![10 as u8, 11, 12, 13, 14];
//!
//! let n = u8s_copy(&mut l, &r);
//!
//! assert_eq!(n, 3);
//! assert_eq!(l, vec![10 as u8, 11, 12]);
//! ```
//!
//! Similar to `copy`, we can use `clone`.
//!
//! ```
//! use slice_copy::clone;
//! 
//! let mut l = b"foobarbaz".to_vec();
//! let r = b"biz".to_vec();
//!
//! let n = clone(&mut l, &r);
//!
//! assert_eq!(n, 3);
//! assert_eq!(l, b"bizbarbaz");
//! ```

use std::cmp::min;

/// Copies as many `u8` as possible from `src` into `dst`, returning the number of `u8` copied.
/// This function is a special case of [`copy`]; `u8` slices have a special optimization for
/// reading if they are of length 1.
///
/// [`copy`]: fn.copy.html
#[inline]
pub fn u8s_copy(dst: &mut [u8], src: &[u8]) -> usize {
    // Read for &[u8] special cases 1-length slices.
    use std::io::Read;
    let len = min(src.len(), dst.len());
    (&src[..len]).read(&mut dst[..len]).expect("&[u8] reads never error")
}

/// Copies as many `T` as possible from `src` into `dst`, returning the number of `T` copied. This
/// function is short form for `dst.copy_from_slice(src)`, but accounts for if their lengths are
/// unequal to avoid panics.
#[inline]
pub fn copy<T>(dst: &mut[T], src: &[T]) -> usize
where T: Copy
{
    let len = min(src.len(), dst.len());
    (&mut dst[..len]).copy_from_slice(&src[..len]);
    len
}

/// Clones as many `T` as possible from `src` into `dst`, returning the number of `T` cloned. This
/// function is short form for `dst.clone_from_slice(src)`, but accounts for if their lengths are
/// unequal to avoid panics.
#[inline]
pub fn clone<T>(dst: &mut[T], src: &[T]) -> usize
where T: Clone
{
    let len = min(src.len(), dst.len());
    (&mut dst[..len]).clone_from_slice(&src[..len]);
    len
}

#[test]
fn test_copy() {
    fn lr() -> (Vec<u8>, Vec<u8>) {
        (b"hello".to_vec(), b"goodbye".to_vec())
    }

    // longer to shorter
    let (mut l, r) = lr();
    assert_eq!(u8s_copy(&mut l, &r), 5);
    assert_eq!(l, b"goodb");
    assert_eq!(r, b"goodbye");

    // shorter to longer
    let (l, mut r) = lr();
    assert_eq!(u8s_copy(&mut r, &l[..4]), 4);
    assert_eq!(l, b"hello");
    assert_eq!(r, b"hellbye");

    // dst length 0
    let (mut l, r) = lr();
    assert_eq!(u8s_copy(&mut l[..0], &r), 0);
    assert_eq!(l, b"hello");
    assert_eq!(r, b"goodbye");

    // src length 0
    assert_eq!(u8s_copy(&mut l, &r[..0]), 0);
    assert_eq!(l, b"hello");
    assert_eq!(r, b"goodbye");
}