Skip to main content

fake_mmio/
operand.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::atomic::AtomicOperand;
6use crate::inject::{VmoMemoryHandler, VmoOpHelper};
7
8/// Trait for MMIO operand types that can be loaded or stored via a test
9/// handler.
10///
11/// This trait is local version of [`mmio::MmioOperand`] with extensions
12/// specifically tailored for testing.
13pub trait MmioOperand:
14    mmio::MmioOperand + AtomicOperand + sealed::MmioOperand + TryFrom<usize, Error: std::fmt::Debug>
15{
16    /// Dispatches a load operation of this operand type to `handler`.
17    fn load<H: VmoMemoryHandler + ?Sized>(handler: &H, op: VmoOpHelper<'_, Self>) -> Self;
18
19    /// Dispatches a store operation of this operand type to `handler`.
20    fn store<H: VmoMemoryHandler + ?Sized>(handler: &H, op: VmoOpHelper<'_, Self>, value: Self);
21}
22
23impl MmioOperand for u8 {
24    fn load<H: VmoMemoryHandler + ?Sized>(handler: &H, op: VmoOpHelper<'_, Self>) -> Self {
25        handler.load8(op)
26    }
27
28    fn store<H: VmoMemoryHandler + ?Sized>(handler: &H, op: VmoOpHelper<'_, Self>, value: Self) {
29        handler.store8(op, value);
30    }
31}
32
33impl MmioOperand for u16 {
34    fn load<H: VmoMemoryHandler + ?Sized>(handler: &H, op: VmoOpHelper<'_, Self>) -> Self {
35        handler.load16(op)
36    }
37
38    fn store<H: VmoMemoryHandler + ?Sized>(handler: &H, op: VmoOpHelper<'_, Self>, value: Self) {
39        handler.store16(op, value);
40    }
41}
42
43impl MmioOperand for u32 {
44    fn load<H: VmoMemoryHandler + ?Sized>(handler: &H, op: VmoOpHelper<'_, Self>) -> Self {
45        handler.load32(op)
46    }
47
48    fn store<H: VmoMemoryHandler + ?Sized>(handler: &H, op: VmoOpHelper<'_, Self>, value: Self) {
49        handler.store32(op, value);
50    }
51}
52
53impl MmioOperand for u64 {
54    fn load<H: VmoMemoryHandler + ?Sized>(handler: &H, op: VmoOpHelper<'_, Self>) -> Self {
55        handler.load64(op)
56    }
57
58    fn store<H: VmoMemoryHandler + ?Sized>(handler: &H, op: VmoOpHelper<'_, Self>, value: Self) {
59        handler.store64(op, value);
60    }
61}
62
63mod sealed {
64
65    /// Internal sealed MmioOperand trait as the types implementing this must match the types in
66    /// the loadn/storen trait methods.
67    pub trait MmioOperand {}
68
69    impl MmioOperand for u8 {}
70    impl MmioOperand for u16 {}
71    impl MmioOperand for u32 {}
72    impl MmioOperand for u64 {}
73}
74
75#[cfg(test)]
76pub(crate) mod tests {
77    use super::*;
78
79    /// A helper trait for executing unit test logic generically across all supported
80    /// [`MmioOperand`] types (`u8`, `u16`, `u32`, and `u64`).
81    ///
82    /// This trait simplifies unit testing for MMIO handler implementations by avoiding
83    /// copy-pasted test logic across different operand widths. Implementers define
84    /// [`call<T>`](OperandCallable::call) for generic operand type `T`, and call
85    /// [`call_all`](OperandCallable::call_all) to execute the test for `u8`, `u16`,
86    /// `u32`, and `u64`.
87    pub(crate) trait OperandCallable {
88        /// Executes test logic for a specific operand type `T`.
89        fn call<T: MmioOperand>(&mut self);
90
91        /// Executes [`call`](OperandCallable::call) for `u8`, `u16`, `u32`, and `u64`.
92        fn call_all(mut self)
93        where
94            Self: Sized,
95        {
96            self.call::<u8>();
97            self.call::<u16>();
98            self.call::<u32>();
99            self.call::<u64>();
100        }
101    }
102}