1*60b67249SAndroid Build Coastguard Worker // Copyright 2024 Google LLC 2*60b67249SAndroid Build Coastguard Worker // 3*60b67249SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4*60b67249SAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of 5*60b67249SAndroid Build Coastguard Worker // the License at 6*60b67249SAndroid Build Coastguard Worker // 7*60b67249SAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0 8*60b67249SAndroid Build Coastguard Worker // 9*60b67249SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*60b67249SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11*60b67249SAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12*60b67249SAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under 13*60b67249SAndroid Build Coastguard Worker // the License. 14*60b67249SAndroid Build Coastguard Worker 15*60b67249SAndroid Build Coastguard Worker //! Types related to command arguments. 16*60b67249SAndroid Build Coastguard Worker 17*60b67249SAndroid Build Coastguard Worker use crate::error::{DpeResult, ErrCode}; 18*60b67249SAndroid Build Coastguard Worker use crate::memory::SizedMessage; 19*60b67249SAndroid Build Coastguard Worker use heapless::FnvIndexMap; 20*60b67249SAndroid Build Coastguard Worker use log::error; 21*60b67249SAndroid Build Coastguard Worker 22*60b67249SAndroid Build Coastguard Worker /// Represents the numeric identifier of a command or response argument. 23*60b67249SAndroid Build Coastguard Worker pub type ArgId = u32; 24*60b67249SAndroid Build Coastguard Worker 25*60b67249SAndroid Build Coastguard Worker /// Represents the type of a command or response argument. 26*60b67249SAndroid Build Coastguard Worker #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)] 27*60b67249SAndroid Build Coastguard Worker pub enum ArgTypeSelector { 28*60b67249SAndroid Build Coastguard Worker /// Indicates an argument was not recognized, so its type is unknown. 29*60b67249SAndroid Build Coastguard Worker #[default] 30*60b67249SAndroid Build Coastguard Worker Unknown, 31*60b67249SAndroid Build Coastguard Worker /// Indicates an argument is encoded as a CBOR byte string. 32*60b67249SAndroid Build Coastguard Worker Bytes, 33*60b67249SAndroid Build Coastguard Worker /// Indicates an argument is encoded as a CBOR unsigned integer. 34*60b67249SAndroid Build Coastguard Worker Int, 35*60b67249SAndroid Build Coastguard Worker /// Indicates an argument is encoded as a CBOR true or false simple value. 36*60b67249SAndroid Build Coastguard Worker Bool, 37*60b67249SAndroid Build Coastguard Worker /// Indicates an argument needs additional custom decoding. 38*60b67249SAndroid Build Coastguard Worker Other, 39*60b67249SAndroid Build Coastguard Worker } 40*60b67249SAndroid Build Coastguard Worker 41*60b67249SAndroid Build Coastguard Worker /// Represents a command or response argument value. 42*60b67249SAndroid Build Coastguard Worker #[derive(Clone, Debug, Eq, PartialEq, Hash)] 43*60b67249SAndroid Build Coastguard Worker pub enum ArgValue<'a> { 44*60b67249SAndroid Build Coastguard Worker /// This instantiation borrows a slice of a message buffer that was decoded 45*60b67249SAndroid Build Coastguard Worker /// as a CBOR byte string. The slice needs to live at least as long as 46*60b67249SAndroid Build Coastguard Worker /// this. 47*60b67249SAndroid Build Coastguard Worker BytesArg(&'a [u8]), 48*60b67249SAndroid Build Coastguard Worker /// This instantiation contains a decoded CBOR unsigned integer. 49*60b67249SAndroid Build Coastguard Worker IntArg(u64), 50*60b67249SAndroid Build Coastguard Worker /// This instantiation contains a decoded CBOR boolean value. 51*60b67249SAndroid Build Coastguard Worker BoolArg(bool), 52*60b67249SAndroid Build Coastguard Worker } 53*60b67249SAndroid Build Coastguard Worker 54*60b67249SAndroid Build Coastguard Worker impl<'a> ArgValue<'a> { 55*60b67249SAndroid Build Coastguard Worker /// Creates a new `BytesArg` from a slice, borrowing the slice. from_slice(value: &'a [u8]) -> Self56*60b67249SAndroid Build Coastguard Worker pub fn from_slice(value: &'a [u8]) -> Self { 57*60b67249SAndroid Build Coastguard Worker ArgValue::BytesArg(value) 58*60b67249SAndroid Build Coastguard Worker } 59*60b67249SAndroid Build Coastguard Worker 60*60b67249SAndroid Build Coastguard Worker /// Returns the borrowed slice if this is a BytesArg. 61*60b67249SAndroid Build Coastguard Worker /// 62*60b67249SAndroid Build Coastguard Worker /// # Errors 63*60b67249SAndroid Build Coastguard Worker /// 64*60b67249SAndroid Build Coastguard Worker /// Returns an InternalError error if this is not a BytesArg. try_into_slice(&self) -> DpeResult<&'a [u8]>65*60b67249SAndroid Build Coastguard Worker pub fn try_into_slice(&self) -> DpeResult<&'a [u8]> { 66*60b67249SAndroid Build Coastguard Worker match self { 67*60b67249SAndroid Build Coastguard Worker ArgValue::IntArg(_) | ArgValue::BoolArg(_) => { 68*60b67249SAndroid Build Coastguard Worker error!("ArgValue::try_info_slice called on {:?}", self); 69*60b67249SAndroid Build Coastguard Worker Err(ErrCode::InternalError) 70*60b67249SAndroid Build Coastguard Worker } 71*60b67249SAndroid Build Coastguard Worker ArgValue::BytesArg(value) => Ok(value), 72*60b67249SAndroid Build Coastguard Worker } 73*60b67249SAndroid Build Coastguard Worker } 74*60b67249SAndroid Build Coastguard Worker 75*60b67249SAndroid Build Coastguard Worker /// Returns the value held by an IntArg as a u32. 76*60b67249SAndroid Build Coastguard Worker /// 77*60b67249SAndroid Build Coastguard Worker /// # Errors 78*60b67249SAndroid Build Coastguard Worker /// 79*60b67249SAndroid Build Coastguard Worker /// Returns an InternalError error if this is not an IntArg. try_into_u32(&self) -> DpeResult<u32>80*60b67249SAndroid Build Coastguard Worker pub fn try_into_u32(&self) -> DpeResult<u32> { 81*60b67249SAndroid Build Coastguard Worker match self { 82*60b67249SAndroid Build Coastguard Worker ArgValue::IntArg(i) => Ok((*i).try_into()?), 83*60b67249SAndroid Build Coastguard Worker _ => { 84*60b67249SAndroid Build Coastguard Worker error!("ArgValue::try_into_u32 called on {:?}", self); 85*60b67249SAndroid Build Coastguard Worker Err(ErrCode::InternalError) 86*60b67249SAndroid Build Coastguard Worker } 87*60b67249SAndroid Build Coastguard Worker } 88*60b67249SAndroid Build Coastguard Worker } 89*60b67249SAndroid Build Coastguard Worker 90*60b67249SAndroid Build Coastguard Worker /// Creates a new `IntArg` holding the given u32 `value`. from_u32(value: u32) -> Self91*60b67249SAndroid Build Coastguard Worker pub fn from_u32(value: u32) -> Self { 92*60b67249SAndroid Build Coastguard Worker ArgValue::IntArg(value as u64) 93*60b67249SAndroid Build Coastguard Worker } 94*60b67249SAndroid Build Coastguard Worker 95*60b67249SAndroid Build Coastguard Worker /// Returns the value held by an IntArg as a u64. 96*60b67249SAndroid Build Coastguard Worker /// 97*60b67249SAndroid Build Coastguard Worker /// # Errors 98*60b67249SAndroid Build Coastguard Worker /// 99*60b67249SAndroid Build Coastguard Worker /// Returns an InternalError error if this is not an IntArg. try_into_u64(&self) -> DpeResult<u64>100*60b67249SAndroid Build Coastguard Worker pub fn try_into_u64(&self) -> DpeResult<u64> { 101*60b67249SAndroid Build Coastguard Worker match self { 102*60b67249SAndroid Build Coastguard Worker ArgValue::IntArg(i) => Ok(*i), 103*60b67249SAndroid Build Coastguard Worker _ => { 104*60b67249SAndroid Build Coastguard Worker error!("ArgValue::try_into_u64 called on {:?}", self); 105*60b67249SAndroid Build Coastguard Worker Err(ErrCode::InternalError) 106*60b67249SAndroid Build Coastguard Worker } 107*60b67249SAndroid Build Coastguard Worker } 108*60b67249SAndroid Build Coastguard Worker } 109*60b67249SAndroid Build Coastguard Worker 110*60b67249SAndroid Build Coastguard Worker /// Creates a new `IntArg` holding the given u64 `value`. from_u64(value: u64) -> Self111*60b67249SAndroid Build Coastguard Worker pub fn from_u64(value: u64) -> Self { 112*60b67249SAndroid Build Coastguard Worker ArgValue::IntArg(value) 113*60b67249SAndroid Build Coastguard Worker } 114*60b67249SAndroid Build Coastguard Worker 115*60b67249SAndroid Build Coastguard Worker /// Returns the value held by a BoolArg. 116*60b67249SAndroid Build Coastguard Worker /// 117*60b67249SAndroid Build Coastguard Worker /// # Errors 118*60b67249SAndroid Build Coastguard Worker /// 119*60b67249SAndroid Build Coastguard Worker /// Returns an InternalError error if this is not a BoolArg. try_into_bool(&self) -> DpeResult<bool>120*60b67249SAndroid Build Coastguard Worker pub fn try_into_bool(&self) -> DpeResult<bool> { 121*60b67249SAndroid Build Coastguard Worker match self { 122*60b67249SAndroid Build Coastguard Worker ArgValue::BoolArg(b) => Ok(*b), 123*60b67249SAndroid Build Coastguard Worker _ => { 124*60b67249SAndroid Build Coastguard Worker error!("ArgValue::try_into_bool called on {:?}", self); 125*60b67249SAndroid Build Coastguard Worker Err(ErrCode::InternalError) 126*60b67249SAndroid Build Coastguard Worker } 127*60b67249SAndroid Build Coastguard Worker } 128*60b67249SAndroid Build Coastguard Worker } 129*60b67249SAndroid Build Coastguard Worker 130*60b67249SAndroid Build Coastguard Worker /// Creates a new `BoolArg` holding the given `value`. from_bool(value: bool) -> Self131*60b67249SAndroid Build Coastguard Worker pub fn from_bool(value: bool) -> Self { 132*60b67249SAndroid Build Coastguard Worker ArgValue::BoolArg(value) 133*60b67249SAndroid Build Coastguard Worker } 134*60b67249SAndroid Build Coastguard Worker } 135*60b67249SAndroid Build Coastguard Worker 136*60b67249SAndroid Build Coastguard Worker impl<'a, const S: usize> From<&'a SizedMessage<S>> for ArgValue<'a> { from(message: &'a SizedMessage<S>) -> Self137*60b67249SAndroid Build Coastguard Worker fn from(message: &'a SizedMessage<S>) -> Self { 138*60b67249SAndroid Build Coastguard Worker Self::BytesArg(message.as_slice()) 139*60b67249SAndroid Build Coastguard Worker } 140*60b67249SAndroid Build Coastguard Worker } 141*60b67249SAndroid Build Coastguard Worker 142*60b67249SAndroid Build Coastguard Worker /// Contains a set of command or response arguments in the form of a map from 143*60b67249SAndroid Build Coastguard Worker /// [`ArgId`] to [`ArgValue`]. 144*60b67249SAndroid Build Coastguard Worker pub type ArgMap<'a> = FnvIndexMap<ArgId, ArgValue<'a>, 16>; 145*60b67249SAndroid Build Coastguard Worker 146*60b67249SAndroid Build Coastguard Worker /// Contains a set of argument types in the form of a map from ArgId to 147*60b67249SAndroid Build Coastguard Worker /// [`ArgTypeSelector`]. 148*60b67249SAndroid Build Coastguard Worker pub type ArgTypeMap = FnvIndexMap<ArgId, ArgTypeSelector, 16>; 149