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}