[cbor][rkpvm] Refactor CBOR Value to other type conversion

With the ciborium function Value::into_*.

Test: atest rialto_test
Bug: 313815907
Change-Id: I23873f76bfe9460b581081cb59ed221c5a1443a5
diff --git a/service_vm/comm/src/csr.rs b/service_vm/comm/src/csr.rs
index 2a27f90..f14787f 100644
--- a/service_vm/comm/src/csr.rs
+++ b/service_vm/comm/src/csr.rs
@@ -55,8 +55,8 @@
             return Err(CoseError::UnexpectedItem("array", "array with 2 items"));
         }
         Ok(Self {
-            signed_csr_payload: try_as_bytes(arr.remove(1), "signed_csr_payload")?,
-            dice_cert_chain: try_as_bytes(arr.remove(0), "dice_cert_chain")?,
+            signed_csr_payload: value_to_bytes(arr.remove(1), "signed_csr_payload")?,
+            dice_cert_chain: value_to_bytes(arr.remove(0), "dice_cert_chain")?,
         })
     }
 }
@@ -94,21 +94,28 @@
             return Err(CoseError::UnexpectedItem("array", "array with 2 items"));
         }
         Ok(Self {
-            challenge: try_as_bytes(arr.remove(1), "challenge")?,
-            public_key: try_as_bytes(arr.remove(0), "public_key")?,
+            challenge: value_to_bytes(arr.remove(1), "challenge")?,
+            public_key: value_to_bytes(arr.remove(0), "public_key")?,
         })
     }
 }
 
-/// Reads the provided value `v` as bytes array.
-pub fn try_as_bytes(v: Value, context: &str) -> coset::Result<Vec<u8>> {
-    if let Value::Bytes(data) = v {
-        Ok(data)
-    } else {
-        let v_type = cbor_value_type(&v);
-        error!("The provided value type '{v_type}' is not of type 'bytes': {context}");
-        Err(CoseError::UnexpectedItem(v_type, "bytes"))
-    }
+/// Converts the provided value `v` to bytes array.
+pub fn value_to_bytes(v: Value, context: &'static str) -> coset::Result<Vec<u8>> {
+    v.into_bytes().map_err(|e| to_unexpected_item_error(&e, "bstr", context))
+}
+
+/// Builds a `CoseError::UnexpectedItem` error when the provided value `v` is not of the expected
+/// type `expected_type` and logs the error message with the provided `context`.
+pub fn to_unexpected_item_error(
+    v: &Value,
+    expected_type: &'static str,
+    context: &'static str,
+) -> CoseError {
+    let v_type = cbor_value_type(v);
+    assert!(v_type != expected_type);
+    error!("The provided value type '{v_type}' is not of type '{expected_type}': {context}");
+    CoseError::UnexpectedItem(v_type, expected_type)
 }
 
 /// Reads the type of the provided value `v`.
diff --git a/service_vm/comm/src/lib.rs b/service_vm/comm/src/lib.rs
index c9de540..343d48e 100644
--- a/service_vm/comm/src/lib.rs
+++ b/service_vm/comm/src/lib.rs
@@ -23,7 +23,7 @@
 mod message;
 mod vsock;
 
-pub use csr::{cbor_value_type, try_as_bytes, Csr, CsrPayload};
+pub use csr::{cbor_value_type, to_unexpected_item_error, value_to_bytes, Csr, CsrPayload};
 pub use message::{
     ClientVmAttestationParams, EcdsaP256KeyPair, GenerateCertificateRequestParams, Request,
     RequestProcessingError, Response, ServiceVmRequest,
diff --git a/service_vm/requests/src/dice.rs b/service_vm/requests/src/dice.rs
index c220af6..0a5eac1 100644
--- a/service_vm/requests/src/dice.rs
+++ b/service_vm/requests/src/dice.rs
@@ -15,7 +15,7 @@
 //! This module contains functions related to DICE.
 
 use alloc::vec::Vec;
-use ciborium::value::Value;
+use ciborium::value::{Integer, Value};
 use core::cell::OnceCell;
 use core::result;
 use coset::{
@@ -23,7 +23,9 @@
 };
 use diced_open_dice::{DiceMode, HASH_SIZE};
 use log::error;
-use service_vm_comm::{cbor_value_type, try_as_bytes, RequestProcessingError};
+use service_vm_comm::{
+    cbor_value_type, to_unexpected_item_error, value_to_bytes, RequestProcessingError,
+};
 
 type Result<T> = result::Result<T, RequestProcessingError>;
 
@@ -101,9 +103,9 @@
     service_vm_dice_chain: &[u8],
 ) -> Result<Vec<Value>> {
     let client_vm_dice_chain =
-        try_as_value_array(Value::from_slice(client_vm_dice_chain)?, "client_vm_dice_chain")?;
+        value_to_array(Value::from_slice(client_vm_dice_chain)?, "client_vm_dice_chain")?;
     let service_vm_dice_chain =
-        try_as_value_array(Value::from_slice(service_vm_dice_chain)?, "service_vm_dice_chain")?;
+        value_to_array(Value::from_slice(service_vm_dice_chain)?, "service_vm_dice_chain")?;
     if service_vm_dice_chain.len() < 3 {
         // The service VM's DICE chain must contain the root key and at least two other entries
         // that describe:
@@ -180,10 +182,7 @@
             error!("No payload found in the DICE chain entry");
             RequestProcessingError::InvalidDiceChain
         })?;
-        let payload = Value::from_slice(&payload)?;
-        let Value::Map(entries) = payload else {
-            return Err(CoseError::UnexpectedItem(cbor_value_type(&payload), "map").into());
-        };
+        let entries = value_to_map(Value::from_slice(&payload)?, "DiceChainEntryPayload")?;
         build_payload(entries)
     }
 }
@@ -191,41 +190,51 @@
 fn build_payload(entries: Vec<(Value, Value)>) -> Result<DiceChainEntryPayload> {
     let mut builder = PayloadBuilder::default();
     for (key, value) in entries.into_iter() {
-        let Some(Ok(key)) = key.as_integer().map(i64::try_from) else {
-            error!("Invalid key found in the DICE chain entry: {:?}", key);
-            return Err(RequestProcessingError::InvalidDiceChain);
-        };
+        let key: i64 = value_to_num(key, "DiceChainEntryPayload key")?;
         match key {
             SUBJECT_PUBLIC_KEY => {
-                let subject_public_key = try_as_bytes(value, "subject_public_key")?;
+                let subject_public_key = value_to_bytes(value, "subject_public_key")?;
                 let subject_public_key = CoseKey::from_slice(&subject_public_key)?.try_into()?;
                 builder.subject_public_key(subject_public_key)?;
             }
             MODE => builder.mode(to_mode(value)?)?,
-            CODE_HASH => builder.code_hash(try_as_byte_array(value, "code_hash")?)?,
-            AUTHORITY_HASH => {
-                builder.authority_hash(try_as_byte_array(value, "authority_hash")?)?
+            CODE_HASH => {
+                let code_hash = value_to_byte_array(value, "DiceChainEntryPayload code_hash")?;
+                builder.code_hash(code_hash)?;
             }
-            CONFIG_DESC => builder.config_descriptor(try_as_bytes(value, "config_descriptor")?)?,
+            AUTHORITY_HASH => {
+                let authority_hash =
+                    value_to_byte_array(value, "DiceChainEntryPayload authority_hash")?;
+                builder.authority_hash(authority_hash)?;
+            }
+            CONFIG_DESC => {
+                let config_descriptor = value_to_bytes(value, "config_descriptor")?;
+                builder.config_descriptor(config_descriptor)?;
+            }
             _ => {}
         }
     }
     builder.build()
 }
 
-fn try_as_value_array(v: Value, context: &str) -> coset::Result<Vec<Value>> {
-    if let Value::Array(data) = v {
-        Ok(data)
-    } else {
-        let v_type = cbor_value_type(&v);
-        error!("The provided value type '{v_type}' is not of type 'bytes': {context}");
-        Err(CoseError::UnexpectedItem(v_type, "array"))
-    }
+fn value_to_array(v: Value, context: &'static str) -> coset::Result<Vec<Value>> {
+    v.into_array().map_err(|e| to_unexpected_item_error(&e, "array", context))
 }
 
-fn try_as_byte_array<const N: usize>(v: Value, context: &str) -> Result<[u8; N]> {
-    let data = try_as_bytes(v, context)?;
-    data.try_into().map_err(|e| {
+fn value_to_map(v: Value, context: &'static str) -> coset::Result<Vec<(Value, Value)>> {
+    v.into_map().map_err(|e| to_unexpected_item_error(&e, "map", context))
+}
+
+fn value_to_num<T: TryFrom<Integer>>(v: Value, context: &'static str) -> Result<T> {
+    let num = v.into_integer().map_err(|e| to_unexpected_item_error(&e, "int", context))?;
+    num.try_into().map_err(|_| {
+        error!("The provided value '{num:?}' is not a valid number: {context}");
+        RequestProcessingError::InvalidDiceChain
+    })
+}
+
+fn value_to_byte_array<const N: usize>(v: Value, context: &'static str) -> Result<[u8; N]> {
+    value_to_bytes(v, context)?.try_into().map_err(|e| {
         error!("The provided value '{context}' is not an array of length {N}: {e:?}");
         RequestProcessingError::InternalError
     })