use std::ops::{Deref, DerefMut};
use serde::{ser::SerializeMap, Serialize, Serializer};
use tonic::metadata::{Ascii, KeyRef, MetadataKey, MetadataMap, MetadataValue};
use crate::error::Error;
#[derive(Debug, Clone)]
pub struct Metadata {
pub(crate) inner: MetadataMap,
}
impl Default for Metadata {
fn default() -> Self {
Self::new()
}
}
impl Metadata {
#[must_use]
pub fn new() -> Self {
Self {
inner: MetadataMap::new(),
}
}
pub fn insert_ascii(&mut self, key: &str, val: &str) -> crate::error::Result<()> {
let key: MetadataKey<Ascii> = key.parse().map_err(|_| Error::ParseToAsciiError)?;
let val: MetadataValue<Ascii> = val.parse().map_err(|_| Error::ParseToAsciiError)?;
self.insert(key, val);
Ok(())
}
pub fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
let len = self.inner.len();
let mut map = ser.serialize_map(Some(len))?;
for key in self.inner.keys() {
if let KeyRef::Ascii(ascii_key) = key {
let Some(value) = self.inner.get(ascii_key) else {
continue;
};
let key_str = ascii_key.to_string();
let Ok(value_str) = value.to_str() else {
continue;
};
map.serialize_entry(&key_str, value_str)?;
}
}
map.end()
}
}
impl Serialize for Metadata {
fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
let len = self.inner.len();
let mut map = serializer.serialize_map(Some(len))?;
for key in self.inner.keys() {
if let KeyRef::Ascii(ascii_key) = key {
let value = self.inner.get(ascii_key).unwrap();
let key_str = ascii_key.to_string();
let value_str = value.to_str().unwrap();
map.serialize_entry(&key_str, value_str)?;
}
}
map.end()
}
}
impl Deref for Metadata {
type Target = MetadataMap;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for Metadata {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_serialize() {
let mut metadata = Metadata::new();
metadata.insert_ascii("auth", "bearer").unwrap();
metadata.insert_ascii("alias", "xx").unwrap();
let mut s = serde_json::Serializer::new(Vec::new());
metadata.serialize(&mut s).unwrap();
let json = String::from_utf8(s.into_inner()).unwrap();
let expected_json = "{\"auth\":\"bearer\",\"alias\":\"xx\"}";
assert_eq!(json, expected_json);
}
}