kernel/utilities/copy_slice.rs
1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Helper functions for copying buffers.
6//!
7//! This utility provides an implementation of the standard Rust
8//! [`slice::copy_from_slice()`] method that cannot panic. This method is
9//! provided through the [`CopyOrErr`] trait.
10//!
11//! This functionality is currently provided for the following types:
12//! - `u8`
13//! - `u16`
14//! - `u32`
15//! - `u64`
16//! - `usize`
17
18use crate::ErrorCode;
19use core::ptr;
20
21/// Interface for copying buffers that cannot panic.
22pub trait CopyOrErr {
23 /// Copy a non-overlapping slice from `src` to `self`.
24 ///
25 /// This is a non-panicking version of [`slice::copy_from_slice`].
26 ///
27 /// Returns `Err(ErrorCode)` if `src` and `self` are not the same length.
28 fn copy_from_slice_or_err(&mut self, src: &Self) -> Result<(), ErrorCode>;
29}
30
31impl CopyOrErr for [u8] {
32 fn copy_from_slice_or_err(&mut self, src: &Self) -> Result<(), ErrorCode> {
33 if self.len() == src.len() {
34 // SAFETY: `self` is valid for `self.len()` elements by definition,
35 // and `src` was checked to have the same length. The slices cannot
36 // overlap because mutable references are exclusive.
37 unsafe {
38 ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
39 }
40 Ok(())
41 } else {
42 Err(ErrorCode::SIZE)
43 }
44 }
45}
46
47impl CopyOrErr for [u16] {
48 fn copy_from_slice_or_err(&mut self, src: &Self) -> Result<(), ErrorCode> {
49 if self.len() == src.len() {
50 // SAFETY: `self` is valid for `self.len()` elements by definition,
51 // and `src` was checked to have the same length. The slices cannot
52 // overlap because mutable references are exclusive.
53 unsafe {
54 ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
55 }
56 Ok(())
57 } else {
58 Err(ErrorCode::SIZE)
59 }
60 }
61}
62
63impl CopyOrErr for [u32] {
64 fn copy_from_slice_or_err(&mut self, src: &Self) -> Result<(), ErrorCode> {
65 if self.len() == src.len() {
66 // SAFETY: `self` is valid for `self.len()` elements by definition,
67 // and `src` was checked to have the same length. The slices cannot
68 // overlap because mutable references are exclusive.
69 unsafe {
70 ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
71 }
72 Ok(())
73 } else {
74 Err(ErrorCode::SIZE)
75 }
76 }
77}
78
79impl CopyOrErr for [u64] {
80 fn copy_from_slice_or_err(&mut self, src: &Self) -> Result<(), ErrorCode> {
81 if self.len() == src.len() {
82 // SAFETY: `self` is valid for `self.len()` elements by definition,
83 // and `src` was checked to have the same length. The slices cannot
84 // overlap because mutable references are exclusive.
85 unsafe {
86 ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
87 }
88 Ok(())
89 } else {
90 Err(ErrorCode::SIZE)
91 }
92 }
93}
94
95impl CopyOrErr for [usize] {
96 fn copy_from_slice_or_err(&mut self, src: &Self) -> Result<(), ErrorCode> {
97 if self.len() == src.len() {
98 // SAFETY: `self` is valid for `self.len()` elements by definition,
99 // and `src` was checked to have the same length. The slices cannot
100 // overlap because mutable references are exclusive.
101 unsafe {
102 ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
103 }
104 Ok(())
105 } else {
106 Err(ErrorCode::SIZE)
107 }
108 }
109}