Skip to main content

wireman_core/descriptor/
metadata.rs

1use std::ops::{Deref, DerefMut};
2
3use serde::{ser::SerializeMap, Serialize, Serializer};
4use tonic::metadata::{Ascii, KeyRef, MetadataKey, MetadataMap, MetadataValue};
5
6use crate::error::Error;
7
8/// Represents `gRPC` metadata, which contains key-value pairs. Metadata is commonly used to
9/// provide additional information with `gRPC` requests and responses.
10#[derive(Debug, Clone)]
11pub struct Metadata {
12    pub(crate) inner: MetadataMap,
13}
14
15impl Default for Metadata {
16    /// Create a new `Metadata` instance with default values.
17    fn default() -> Self {
18        Self::new()
19    }
20}
21
22impl Metadata {
23    /// Create a new `Metadata` instance.
24    #[must_use]
25    pub fn new() -> Self {
26        Self {
27            inner: MetadataMap::new(),
28        }
29    }
30
31    /// Insert an ASCII key-value pair into the metadata.
32    ///
33    /// # Errors
34    ///
35    /// Returns an error if parsing the key or value to ASCII fails.
36    pub fn insert_ascii(&mut self, key: &str, val: &str) -> crate::error::Result<()> {
37        let key: MetadataKey<Ascii> = key.parse().map_err(|_| Error::ParseToAsciiError)?;
38        let val: MetadataValue<Ascii> = val.parse().map_err(|_| Error::ParseToAsciiError)?;
39        self.insert(key, val);
40        Ok(())
41    }
42
43    /// Serialize the metadata to a format compatible with the given serializer.
44    ///
45    /// # Errors
46    ///
47    /// Returns an error if serializing the metadata map fails
48    pub fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
49        let len = self.inner.len();
50        let mut map = ser.serialize_map(Some(len))?;
51        for key in self.inner.keys() {
52            if let KeyRef::Ascii(ascii_key) = key {
53                let Some(value) = self.inner.get(ascii_key) else {
54                    continue;
55                };
56                let key_str = ascii_key.to_string();
57                let Ok(value_str) = value.to_str() else {
58                    continue;
59                };
60                map.serialize_entry(&key_str, value_str)?;
61            }
62        }
63        map.end()
64    }
65}
66
67impl Serialize for Metadata {
68    fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
69    where
70        S: Serializer,
71    {
72        let len = self.inner.len();
73        let mut map = serializer.serialize_map(Some(len))?;
74        for key in self.inner.keys() {
75            if let KeyRef::Ascii(ascii_key) = key {
76                let value = self.inner.get(ascii_key).unwrap();
77                let key_str = ascii_key.to_string();
78                let value_str = value.to_str().unwrap();
79                map.serialize_entry(&key_str, value_str)?;
80            }
81        }
82        map.end()
83    }
84}
85
86impl Deref for Metadata {
87    type Target = MetadataMap;
88
89    fn deref(&self) -> &Self::Target {
90        &self.inner
91    }
92}
93
94impl DerefMut for Metadata {
95    fn deref_mut(&mut self) -> &mut Self::Target {
96        &mut self.inner
97    }
98}
99
100#[cfg(test)]
101mod test {
102
103    use super::*;
104
105    #[test]
106    fn test_serialize() {
107        // given
108        let mut metadata = Metadata::new();
109        metadata.insert_ascii("auth", "bearer").unwrap();
110        metadata.insert_ascii("alias", "xx").unwrap();
111
112        let mut s = serde_json::Serializer::new(Vec::new());
113
114        // when
115        metadata.serialize(&mut s).unwrap();
116        let json = String::from_utf8(s.into_inner()).unwrap();
117
118        // then
119        let expected_json = "{\"auth\":\"bearer\",\"alias\":\"xx\"}";
120        assert_eq!(json, expected_json);
121    }
122}