// 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 { 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 { 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 { 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> for ArgValue<'a> { fn from(message: &'a SizedMessage) -> 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, 16>; /// Contains a set of argument types in the form of a map from ArgId to /// [`ArgTypeSelector`]. pub type ArgTypeMap = FnvIndexMap;