Как идиоматически копировать фрагмент?
В Go копирование фрагментов выполняется стандартно и выглядит следующим образом:
# It will figure out the details to match slice sizes
dst = copy(dst[n:], src[:m])
В Rust я не смог найти аналогичный метод в качестве замены. Что-то, что я придумал, выглядит так:
fn copy_slice(dst: &mut [u8], src: &[u8]) -> usize {
let mut c = 0;
for (&mut d, &s) in dst.iter_mut().zip(src.iter()) {
d = s;
c += 1;
}
c
}
К сожалению, я получаю эту ошибку компиляции, которую я не могу решить:
error[E0384]: re-assignment of immutable variable 'd'
--> src/main.rs:4:9
|
3 | for (&mut d, &s) in dst.iter_mut().zip(src.iter()) {
| - first assignment to 'd'
4 | d = s;
| ^^^^^ re-assignment of immutable variable
Как я могу установить d
? Есть ли лучший способ скопировать фрагмент?
Ответы
Ответ 1
Да, используйте метод clone_from_slice()
, он является общим для любого типа элемента, который реализует Clone
.
fn main() {
let mut x = vec![0; 8];
let y = [1, 2, 3];
x[..3].clone_from_slice(&y);
println!("{:?}", x);
// Output:
// [1, 2, 3, 0, 0, 0, 0, 0]
}
Пункт назначения x
является либо срезом &mut [T]
, либо чем-либо, что derefs к нему, как измененный Vec<T>
вектор. Вам нужно нарезать место назначения и источник так, чтобы их длина соответствовала.
Начиная с Rust 1.9, вы также можете использовать copy_from_slice()
. Это работает одинаково, но использует Copy
признак вместо Clone
и является прямой оболочкой memcpy
. Компилятор может оптимизировать clone_from_slice
, чтобы быть эквивалентным copy_from_slice
, когда это применимо, но он может быть полезен.
Ответ 2
Предупреждение copy_memory
устарело с Rust 1.6.0. Проверьте bluss ' для стабильного решения.
Я бы использовал copy_memory
, который имеет почти ту же подпись, что и вы:
use std::slice::bytes;
use std::cmp;
fn copy_slice(dst: &mut [u8], src: &[u8]) -> usize {
let len = cmp::min(src.len(), dst.len());
bytes::copy_memory(&mut dst[..len], &src[..len]);
len
}
fn main() {
let mut a = [1u8, 2, 3];
let mut b = [9u8];
//copy_slice(&mut a[], &b[]);
copy_slice(&mut b[], &a[]);
println!("{:?}, {:?}", a, b);
}
Обратите внимание, что это не общее решение. В ржавчине срезы могут быть любого типа, включая те, которые нелегко копировать! Ваш вопрос и этот ответ касаются только фрагментов u8
.
Ответ 3
Этот код работает, хотя я не уверен, что это лучший способ сделать это.
fn copy_slice(dst: &mut [u8], src: &[u8]) -> usize {
let mut c = 0;
for (d, s) in dst.iter_mut().zip(src.iter()) {
*d = *s;
c += 1;
}
c
}
По-видимому, не указав разрешения доступа, явно сделал трюк. Тем не менее, я все еще смущен этим, и моя ментальная модель еще не охватывает то, что действительно происходит там.
Мои решения в основном являются пробными и ошибочными, когда дело доходит до этих вещей, и я бы предпочел по-настоящему понять.
Ответ 4
Другим вариантом будет
fn copy_slice(dst: &mut [u8], src: &[u8]) -> usize {
dst.iter_mut().zip(src).map(|(x, y)| *x = *y).count()
}
Обратите внимание, что в этом случае вы должны использовать count
, так как len
будет использовать ярлык ExactSizeIterator
и, таким образом, никогда не будет вызывать next
, в результате получится no-op.