wick_packet/
context.rs

1use std::collections::HashMap;
2
3use serde::de::DeserializeOwned;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7use crate::{ComponentReference, Error, InherentData};
8
9#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
10pub struct RuntimeConfig(HashMap<String, Value>);
11
12impl RuntimeConfig {
13  /// Get a value from the configuration map, deserializing it into the target type.
14  pub fn coerce_key<T>(&self, key: &str) -> Result<T, Error>
15  where
16    T: DeserializeOwned,
17  {
18    let value = self.0.get(key).ok_or_else(|| Error::ContextKey(key.to_owned()))?;
19    serde_json::from_value(value.clone()).map_err(|_| Error::ContextKey(key.to_owned()))
20  }
21
22  /// Check if a value exists in the configuration map.
23  #[must_use]
24  pub fn has(&self, key: &str) -> bool {
25    self.0.contains_key(key)
26  }
27
28  /// Get a value from the configuration map.
29  #[must_use]
30  pub fn get(&self, key: &str) -> Option<&Value> {
31    self.0.get(key)
32  }
33
34  /// Convert a [serde_json::Value] into a [RuntimeConfig].
35  pub fn from_value(value: Value) -> Result<Self, Error> {
36    match value {
37      Value::Object(map) => {
38        let mut hm = HashMap::new();
39        for (k, v) in map {
40          hm.insert(k, v);
41        }
42        Ok(Self(hm))
43      }
44      _ => Err(Error::BadJson(value)),
45    }
46  }
47}
48
49impl IntoIterator for RuntimeConfig {
50  type Item = (String, Value);
51  type IntoIter = std::collections::hash_map::IntoIter<String, Value>;
52
53  fn into_iter(self) -> Self::IntoIter {
54    self.0.into_iter()
55  }
56}
57
58impl From<HashMap<String, Value>> for RuntimeConfig {
59  fn from(value: HashMap<String, Value>) -> Self {
60    Self(value)
61  }
62}
63
64impl From<RuntimeConfig> for HashMap<String, Value> {
65  fn from(value: RuntimeConfig) -> Self {
66    value.0
67  }
68}
69
70impl<K, const N: usize> From<[(K, Value); N]> for RuntimeConfig
71where
72  K: Into<String>,
73{
74  /// # Examples
75  ///
76  /// ```
77  /// use wick_packet::RuntimeConfig;
78  ///
79  /// let config = RuntimeConfig::from([("key1", "value".into()), ("key2", 4.into())]);
80  /// let key1 = config.coerce_key::<String>("key1").unwrap();
81  /// assert_eq!(key1, "value");
82  ///
83  /// let key2 = config.coerce_key::<u16>("key2").unwrap();
84  /// assert_eq!(key2, 4);
85  ///
86  /// ```
87  fn from(arr: [(K, Value); N]) -> Self {
88    Self(HashMap::from_iter(arr.into_iter().map(|(k, v)| (k.into(), v))))
89  }
90}
91
92impl TryFrom<Value> for RuntimeConfig {
93  type Error = Error;
94
95  fn try_from(value: Value) -> Result<Self, Self::Error> {
96    match value {
97      Value::Object(map) => {
98        let mut hm = HashMap::new();
99        for (k, v) in map {
100          hm.insert(k, v);
101        }
102        Ok(Self(hm))
103      }
104      _ => Err(Error::BadJson(value)),
105    }
106  }
107}
108
109#[derive(Deserialize, Serialize, Debug)]
110#[non_exhaustive]
111pub struct ContextTransport<T>
112where
113  T: std::fmt::Debug + Serialize,
114{
115  pub config: T,
116  pub inherent: InherentData,
117  pub invocation: Option<InvocationRequest>,
118}
119
120impl<T> ContextTransport<T>
121where
122  T: std::fmt::Debug + Serialize,
123{
124  pub const fn new(config: T, inherent: InherentData) -> Self {
125    Self {
126      config,
127      inherent,
128      invocation: None,
129    }
130  }
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
134#[non_exhaustive]
135#[must_use]
136pub struct InvocationRequest {
137  pub reference: ComponentReference,
138  pub operation: String,
139}