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}