|  | // Copyright 2024 Google LLC | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); you may not | 
|  | // use this file except in compliance with the License. You may obtain a copy of | 
|  | // the License at | 
|  | // | 
|  | //     https://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | 
|  | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | 
|  | // License for the specific language governing permissions and limitations under | 
|  | // the License. | 
|  |  | 
|  | //! Types related to command arguments. | 
|  |  | 
|  | use crate::error::{DpeResult, ErrCode}; | 
|  | use crate::memory::SizedMessage; | 
|  | use heapless::FnvIndexMap; | 
|  | use log::error; | 
|  |  | 
|  | /// Represents the numeric identifier of a command or response argument. | 
|  | pub type ArgId = u32; | 
|  |  | 
|  | /// Represents the type of a command or response argument. | 
|  | #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)] | 
|  | pub enum ArgTypeSelector { | 
|  | /// Indicates an argument was not recognized, so its type is unknown. | 
|  | #[default] | 
|  | Unknown, | 
|  | /// Indicates an argument is encoded as a CBOR byte string. | 
|  | Bytes, | 
|  | /// Indicates an argument is encoded as a CBOR unsigned integer. | 
|  | Int, | 
|  | /// Indicates an argument is encoded as a CBOR true or false simple value. | 
|  | Bool, | 
|  | /// Indicates an argument needs additional custom decoding. | 
|  | Other, | 
|  | } | 
|  |  | 
|  | /// Represents a command or response argument value. | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Hash)] | 
|  | pub enum ArgValue<'a> { | 
|  | /// This instantiation borrows a slice of a message buffer that was decoded | 
|  | /// as a CBOR byte string. The slice needs to live at least as long as | 
|  | /// this. | 
|  | BytesArg(&'a [u8]), | 
|  | /// This instantiation contains a decoded CBOR unsigned integer. | 
|  | IntArg(u64), | 
|  | /// This instantiation contains a decoded CBOR boolean value. | 
|  | BoolArg(bool), | 
|  | } | 
|  |  | 
|  | impl<'a> ArgValue<'a> { | 
|  | /// Creates a new `BytesArg` from a slice, borrowing the slice. | 
|  | pub fn from_slice(value: &'a [u8]) -> Self { | 
|  | ArgValue::BytesArg(value) | 
|  | } | 
|  |  | 
|  | /// Returns the borrowed slice if this is a BytesArg. | 
|  | /// | 
|  | /// # Errors | 
|  | /// | 
|  | /// Returns an InternalError error if this is not a BytesArg. | 
|  | pub fn try_into_slice(&self) -> DpeResult<&'a [u8]> { | 
|  | match self { | 
|  | ArgValue::IntArg(_) | ArgValue::BoolArg(_) => { | 
|  | error!("ArgValue::try_info_slice called on {:?}", self); | 
|  | Err(ErrCode::InternalError) | 
|  | } | 
|  | ArgValue::BytesArg(value) => Ok(value), | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Returns the value held by an IntArg as a u32. | 
|  | /// | 
|  | /// # Errors | 
|  | /// | 
|  | /// Returns an InternalError error if this is not an IntArg. | 
|  | pub fn try_into_u32(&self) -> DpeResult<u32> { | 
|  | match self { | 
|  | ArgValue::IntArg(i) => Ok((*i).try_into()?), | 
|  | _ => { | 
|  | error!("ArgValue::try_into_u32 called on {:?}", self); | 
|  | Err(ErrCode::InternalError) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Creates a new `IntArg` holding the given u32 `value`. | 
|  | pub fn from_u32(value: u32) -> Self { | 
|  | ArgValue::IntArg(value as u64) | 
|  | } | 
|  |  | 
|  | /// Returns the value held by an IntArg as a u64. | 
|  | /// | 
|  | /// # Errors | 
|  | /// | 
|  | /// Returns an InternalError error if this is not an IntArg. | 
|  | pub fn try_into_u64(&self) -> DpeResult<u64> { | 
|  | match self { | 
|  | ArgValue::IntArg(i) => Ok(*i), | 
|  | _ => { | 
|  | error!("ArgValue::try_into_u64 called on {:?}", self); | 
|  | Err(ErrCode::InternalError) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Creates a new `IntArg` holding the given u64 `value`. | 
|  | pub fn from_u64(value: u64) -> Self { | 
|  | ArgValue::IntArg(value) | 
|  | } | 
|  |  | 
|  | /// Returns the value held by a BoolArg. | 
|  | /// | 
|  | /// # Errors | 
|  | /// | 
|  | /// Returns an InternalError error if this is not a BoolArg. | 
|  | pub fn try_into_bool(&self) -> DpeResult<bool> { | 
|  | match self { | 
|  | ArgValue::BoolArg(b) => Ok(*b), | 
|  | _ => { | 
|  | error!("ArgValue::try_into_bool called on {:?}", self); | 
|  | Err(ErrCode::InternalError) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Creates a new `BoolArg` holding the given `value`. | 
|  | pub fn from_bool(value: bool) -> Self { | 
|  | ArgValue::BoolArg(value) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<'a, const S: usize> From<&'a SizedMessage<S>> for ArgValue<'a> { | 
|  | fn from(message: &'a SizedMessage<S>) -> Self { | 
|  | Self::BytesArg(message.as_slice()) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Contains a set of command or response arguments in the form of a map from | 
|  | /// [`ArgId`] to [`ArgValue`]. | 
|  | pub type ArgMap<'a> = FnvIndexMap<ArgId, ArgValue<'a>, 16>; | 
|  |  | 
|  | /// Contains a set of argument types in the form of a map from ArgId to | 
|  | /// [`ArgTypeSelector`]. | 
|  | pub type ArgTypeMap = FnvIndexMap<ArgId, ArgTypeSelector, 16>; |