slice_copy/
lib.rs

1#![no_std]
2
3//! This crate provides Go style copying / cloning for slices.
4//!
5//! This crate is for those times where it is easier to adjust slices based off the number of
6//! elements copied, as opposed to determining the amount to copy before adjusting slices and
7//! finally copying.
8//!
9//! # Examples
10//!
11//! We can use `copy` for types that implement `Copy`.
12//!
13//! ```
14//! use slice_copy::copy;
15//!
16//! let mut l = b"hello".to_vec();
17//! let r = b"goodbye".to_vec();
18//!
19//! let n = copy(&mut l, &r);
20//!
21//! assert_eq!(n, 5);
22//! assert_eq!(l, b"goodb");
23//! ```
24//!
25//! Similarly, we can use `clone` for types that implement `Clone`.
26//!
27//! ```
28//! use slice_copy::clone;
29//!
30//! let mut l = b"foobarbaz".to_vec();
31//! let r = b"biz".to_vec();
32//!
33//! let n = clone(&mut l, &r);
34//!
35//! assert_eq!(n, 3);
36//! assert_eq!(l, b"bizbarbaz");
37//! ```
38
39#[cfg(test)]
40extern crate alloc;
41
42#[cfg(test)]
43use alloc::vec::Vec;
44
45use core::cmp::min;
46
47/// Copies as many `T` as possible from `src` into `dst`, returning the number of `T` copied. This
48/// function is short form for `dst.copy_from_slice(src)`, but accounts for if their lengths are
49/// unequal to avoid panics.
50///
51/// With the `nightly` feature, `[u8]` is specialized to use [`Read`], which is implemented
52/// specially for small slices.
53///
54/// [`Read`]: https://doc.rust-lang.org/std/primitive.slice.html#impl-Read
55///
56/// # Examples
57///
58/// ```
59/// use slice_copy::copy;
60///
61/// let mut l = vec![1 as u8, 2, 3, 4, 5];
62/// let r = vec![10, 11, 12];
63///
64/// let n = copy(&mut l, &r);
65///
66/// assert_eq!(n, 3);
67/// assert_eq!(l, vec![10, 11, 12, 4, 5]);
68/// ```
69#[inline]
70pub fn copy<T>(dst: &mut [T], src: &[T]) -> usize
71where
72    T: Copy,
73{
74    let len = min(src.len(), dst.len());
75    (&mut dst[..len]).copy_from_slice(&src[..len]);
76    len
77}
78
79/// Clones as many `T` as possible from `src` into `dst`, returning the number of `T` cloned. This
80/// function is short form for `dst.clone_from_slice(src)`, but accounts for if their lengths are
81/// unequal to avoid panics.
82///
83/// Examples
84///
85/// ```
86/// use slice_copy::clone;
87///
88/// let mut l = b"left".to_vec();
89/// let r = b"right".to_vec();
90///
91/// let n = clone(&mut l, &r);
92///
93/// assert_eq!(n, 4);
94/// assert_eq!(l, b"righ");
95/// ```
96#[inline]
97pub fn clone<T>(dst: &mut [T], src: &[T]) -> usize
98where
99    T: Clone,
100{
101    let len = min(src.len(), dst.len());
102    (&mut dst[..len]).clone_from_slice(&src[..len]);
103    len
104}
105
106#[test]
107fn test_copy() {
108    fn lr() -> (Vec<u8>, Vec<u8>) {
109        (b"hello".to_vec(), b"goodbye".to_vec())
110    }
111
112    // longer to shorter
113    let (mut l, r) = lr();
114    assert_eq!(copy(&mut l, &r), 5);
115    assert_eq!(l, b"goodb");
116    assert_eq!(r, b"goodbye");
117
118    // shorter to longer
119    let (l, mut r) = lr();
120    assert_eq!(copy(&mut r, &l[..4]), 4);
121    assert_eq!(l, b"hello");
122    assert_eq!(r, b"hellbye");
123
124    // dst length 0
125    let (mut l, r) = lr();
126    assert_eq!(copy(&mut l[..0], &r), 0);
127    assert_eq!(l, b"hello");
128    assert_eq!(r, b"goodbye");
129
130    // src length 0
131    assert_eq!(copy(&mut l, &r[..0]), 0);
132    assert_eq!(l, b"hello");
133    assert_eq!(r, b"goodbye");
134}