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}