kernel/utilities/copy_slice.rs
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
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.
//! Helper functions for copying buffers.
//!
//! This utility provides an implementation of the standard Rust
//! [`slice::copy_from_slice()`] method that cannot panic. This method is
//! provided through the [`CopyOrErr`] trait.
//!
//! This functionality is currently provided for the following types:
//! - `u8`
//! - `u16`
//! - `u32`
//! - `u64`
//! - `usize`
use crate::ErrorCode;
use core::ptr;
/// Interface for copying buffers that cannot panic.
pub trait CopyOrErr {
/// Copy a non-overlapping slice from `src` to `self`.
///
/// This is a non-panicking version of [`slice::copy_from_slice`].
///
/// Returns `Err(ErrorCode)` if `src` and `self` are not the same length.
fn copy_from_slice_or_err(&mut self, src: &Self) -> Result<(), ErrorCode>;
}
impl CopyOrErr for [u8] {
fn copy_from_slice_or_err(&mut self, src: &Self) -> Result<(), ErrorCode> {
if self.len() == src.len() {
// SAFETY: `self` is valid for `self.len()` elements by definition,
// and `src` was checked to have the same length. The slices cannot
// overlap because mutable references are exclusive.
unsafe {
ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
}
Ok(())
} else {
Err(ErrorCode::SIZE)
}
}
}
impl CopyOrErr for [u16] {
fn copy_from_slice_or_err(&mut self, src: &Self) -> Result<(), ErrorCode> {
if self.len() == src.len() {
// SAFETY: `self` is valid for `self.len()` elements by definition,
// and `src` was checked to have the same length. The slices cannot
// overlap because mutable references are exclusive.
unsafe {
ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
}
Ok(())
} else {
Err(ErrorCode::SIZE)
}
}
}
impl CopyOrErr for [u32] {
fn copy_from_slice_or_err(&mut self, src: &Self) -> Result<(), ErrorCode> {
if self.len() == src.len() {
// SAFETY: `self` is valid for `self.len()` elements by definition,
// and `src` was checked to have the same length. The slices cannot
// overlap because mutable references are exclusive.
unsafe {
ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
}
Ok(())
} else {
Err(ErrorCode::SIZE)
}
}
}
impl CopyOrErr for [u64] {
fn copy_from_slice_or_err(&mut self, src: &Self) -> Result<(), ErrorCode> {
if self.len() == src.len() {
// SAFETY: `self` is valid for `self.len()` elements by definition,
// and `src` was checked to have the same length. The slices cannot
// overlap because mutable references are exclusive.
unsafe {
ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
}
Ok(())
} else {
Err(ErrorCode::SIZE)
}
}
}
impl CopyOrErr for [usize] {
fn copy_from_slice_or_err(&mut self, src: &Self) -> Result<(), ErrorCode> {
if self.len() == src.len() {
// SAFETY: `self` is valid for `self.len()` elements by definition,
// and `src` was checked to have the same length. The slices cannot
// overlap because mutable references are exclusive.
unsafe {
ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
}
Ok(())
} else {
Err(ErrorCode::SIZE)
}
}
}