virtio/devices/virtio_gpu/helpers.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 2024.
4
5use kernel::ErrorCode;
6
7/// Const version of `std::cmp::max` for an array of `usize`s.
8///
9/// Used to determine the maximum VirtIO GPU request / response size,
10/// to determine the VirtQueue buffer size required.
11///
12/// This is ... not great. `const fn`s are pretty restrictive still,
13/// and most subslicing or iterator operations can't be used. So this
14/// looks like its the best we can do, at least for now.
15pub const fn max(elems: &[usize]) -> usize {
16 const fn max_inner(elems: &[usize], idx: usize) -> usize {
17 match elems.len() - idx {
18 0 => usize::MIN,
19 1 => elems[idx],
20 _ => {
21 let max_tail = max_inner(elems, idx + 1);
22 if max_tail > elems[idx] {
23 max_tail
24 } else {
25 elems[idx]
26 }
27 }
28 }
29 }
30 max_inner(elems, 0)
31}
32
33/// Helper to copy a buffer into an iterator, returning
34/// `Err(ErrorCode::SIZE)` if it doesn't fit.
35#[inline]
36pub fn copy_to_iter<'a, T: 'a>(
37 dst: &mut impl Iterator<Item = &'a mut T>,
38 src: impl Iterator<Item = T>,
39) -> Result<(), ErrorCode> {
40 for e in src {
41 *dst.next().ok_or(ErrorCode::SIZE)? = e;
42 }
43 Ok(())
44}
45
46/// Create a byte-array from an iterator of `u8`s, returning
47/// `Err(ErrorCode::SIZE)` if the iterator does not yield a sufficient
48/// number of elements.
49#[inline]
50pub fn bytes_from_iter<const N: usize>(
51 src: &mut impl Iterator<Item = u8>,
52) -> Result<[u8; N], ErrorCode> {
53 let mut dst: [u8; N] = [0; N];
54
55 for d in dst.iter_mut() {
56 *d = src.next().ok_or(ErrorCode::SIZE)?;
57 }
58
59 Ok(dst)
60}