spin_locked_app/
metadata.rs1use std::marker::PhantomData;
2
3use serde::Deserialize;
4use serde_json::Value;
5
6use crate::{values::ValuesMap, Error, Result};
7
8pub struct MetadataKey<T = String> {
10 key: &'static str,
11 _phantom: PhantomData<T>,
12}
13
14impl<T> MetadataKey<T> {
15 pub const fn new(key: &'static str) -> Self {
17 Self {
18 key,
19 _phantom: PhantomData,
20 }
21 }
22}
23
24impl<T> Clone for MetadataKey<T> {
25 fn clone(&self) -> Self {
26 *self
27 }
28}
29
30impl<T> Copy for MetadataKey<T> {}
31
32impl<T> AsRef<str> for MetadataKey<T> {
33 fn as_ref(&self) -> &str {
34 self.key
35 }
36}
37
38impl<T> From<MetadataKey<T>> for String {
39 fn from(value: MetadataKey<T>) -> Self {
40 value.key.to_string()
41 }
42}
43
44impl<T> std::fmt::Debug for MetadataKey<T> {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 write!(f, "{:?}", self.key)
47 }
48}
49
50pub trait MetadataExt {
52 fn get_value(&self, key: &str) -> Option<&Value>;
54
55 fn get_typed<'a, T: Deserialize<'a>>(&'a self, key: MetadataKey<T>) -> Result<Option<T>> {
57 self.get_value(key.as_ref())
58 .map(T::deserialize)
59 .transpose()
60 .map_err(|err| {
61 Error::MetadataError(format!("invalid metadata value for {key:?}: {err:?}"))
62 })
63 }
64
65 fn require_typed<'a, T: Deserialize<'a>>(&'a self, key: MetadataKey<T>) -> Result<T> {
68 self.get_typed(key)?
69 .ok_or_else(|| Error::MetadataError(format!("missing required metadata {key:?}")))
70 }
71}
72
73impl MetadataExt for ValuesMap {
74 fn get_value(&self, key: &str) -> Option<&Value> {
75 self.get(key)
76 }
77}