vade_didcomm/
utils.rs

1use std::{
2    convert::TryInto,
3    time::{SystemTime, UNIX_EPOCH},
4};
5
6use uuid::Uuid;
7
8use crate::{
9    datatypes::{BaseMessage, ExtendedMessage, FromTo},
10    db::{read_db, search_db_keys, write_db},
11};
12
13/// Formats an vector into an array dynamically.
14///
15/// # Arguments
16/// * `v` - vector to format
17///
18/// # Returns
19/// * `Array` - the transformed array
20pub fn vec_to_array<T, const N: usize>(v: Vec<T>) -> Result<[T; N], Box<dyn std::error::Error>> {
21    v.try_into()
22        .map_err(|_e| Box::from("could not format vec to array"))
23}
24
25/// Takes an DIDComm message and extracts the basic information that are required.
26///
27/// # Arguments
28/// * `message` - DIDComm message with communication DID document as body
29///
30/// # Returns
31/// * `ExchangeInfo` - necessary information
32pub fn get_from_to_from_message(
33    message: &BaseMessage,
34) -> Result<FromTo, Box<dyn std::error::Error>> {
35    let from_did = message.from.as_ref().ok_or("from is required")?;
36
37    let to_vec = message.to.as_ref().ok_or("to is required")?;
38    if to_vec.is_empty() {
39        return Err(Box::from(
40            "DID exchange requires at least one did in the to field.",
41        ));
42    }
43    let to_did = &to_vec[0];
44
45    Ok(FromTo {
46        from: from_did.to_owned(),
47        to: String::from(to_did),
48    })
49}
50
51/// Write a didcomm_send/didcomm_receive raw message to rocks_db
52///
53/// # Arguments
54/// * `message` - Raw message
55pub fn write_raw_message_to_db(message: &str) -> Result<(), Box<dyn std::error::Error>> {
56    let parsed_raw_message: ExtendedMessage = serde_json::from_str(message)?;
57
58    write_db(
59        &format!(
60            "message_{}_{}",
61            parsed_raw_message
62                .thid
63                .unwrap_or(parsed_raw_message.id.clone().ok_or("id is missing")?),
64            parsed_raw_message.id.ok_or("id is missing")?
65        ),
66        message,
67    )
68}
69
70/// Read a didcomm_send/didcomm_receive raw message from rocks_db
71///
72/// # Arguments
73/// * `message` - Raw message
74pub fn read_raw_message_from_db(
75    prefix: &str,
76    thid: &str,
77    msg_id: &str,
78) -> Result<Vec<String>, Box<dyn std::error::Error>> {
79    let mut key = format!("{}_{}_{}", prefix, thid, msg_id);
80
81    if msg_id == "*" {
82        key = format!("{}_{}", prefix, thid);
83        search_db_keys(&key)
84    } else {
85        let value = read_db(&key)?;
86        Ok(vec![value])
87    }
88}
89
90/// Adds an id and create_time to stringified DIDComm message.
91///
92/// # Arguments
93/// * `message` - DIDComm message
94///
95/// # Returns
96/// * `string` - stringified message
97pub fn fill_message_id_and_timestamps(message: &str) -> Result<String, Box<dyn std::error::Error>> {
98    let mut parsed_message: ExtendedMessage = serde_json::from_str(message)?;
99
100    if parsed_message.id.is_none() {
101        parsed_message.id = Some(Uuid::to_string(&Uuid::new_v4()));
102    }
103
104    if parsed_message.created_time.is_none() {
105        let start = SystemTime::now();
106        let since_the_epoch = start.duration_since(UNIX_EPOCH)?;
107        parsed_message.created_time = Some(since_the_epoch.as_secs());
108    }
109
110    Ok(serde_json::to_string(&parsed_message)?)
111}
112
113pub(crate) mod hex_option {
114    use serde::{Deserialize, Deserializer, Serialize, Serializer};
115
116    pub fn serialize<S: Serializer>(v: &Option<[u8; 32]>, s: S) -> Result<S::Ok, S::Error> {
117        let hex_string = v.as_ref().map(hex::encode);
118        <Option<String>>::serialize(&hex_string, s)
119    }
120
121    pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Option<[u8; 32]>, D::Error> {
122        let hex_string = <Option<String>>::deserialize(d)?;
123        match hex_string {
124            Some(v) => {
125                let hex_decoded = hex::decode(v).map_err(serde::de::Error::custom)?;
126                let mut arr: [u8; 32] = Default::default();
127                arr.copy_from_slice(&hex_decoded[..32]);
128                Ok(Some(arr))
129            }
130            None => Ok(None),
131        }
132    }
133}