use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct Headers {
inner: HashMap<String, String>,
}
impl Headers {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, key: impl Into<String>, value: impl Into<String>) {
self.inner.insert(key.into(), value.into());
}
pub fn merge(&mut self, overlay: Headers) {
for (k, v) in overlay.inner {
self.inner.insert(k, v);
}
}
pub fn merge_with(&mut self, overlay: &Headers) {
for (k, v) in &overlay.inner {
self.inner.insert(k.clone(), v.clone());
}
}
pub fn get(&self, key: &str) -> Option<&String> {
self.inner.get(key)
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn to_reqwest_headers(&self) -> reqwest::header::HeaderMap {
let mut headers = reqwest::header::HeaderMap::new();
for (k, v) in &self.inner {
if let (Ok(name), Ok(value)) = (
reqwest::header::HeaderName::from_bytes(k.as_bytes()),
reqwest::header::HeaderValue::from_str(v),
) {
headers.insert(name, value);
}
}
headers
}
pub fn iter(&self) -> impl Iterator<Item = (&String, &String)> {
self.inner.iter()
}
}
impl From<(String, String)> for Headers {
fn from((key, value): (String, String)) -> Self {
let mut headers = Headers::new();
headers.insert(key, value);
headers
}
}
impl From<(&str, &str)> for Headers {
fn from((key, value): (&str, &str)) -> Self {
let mut headers = Headers::new();
headers.insert(key, value);
headers
}
}
impl From<Vec<(String, String)>> for Headers {
fn from(vec: Vec<(String, String)>) -> Self {
let mut headers = Headers::new();
for (k, v) in vec {
headers.insert(k, v);
}
headers
}
}
impl<const N: usize> From<[(String, String); N]> for Headers {
fn from(arr: [(String, String); N]) -> Self {
let mut headers = Headers::new();
for (k, v) in arr {
headers.insert(k, v);
}
headers
}
}
impl<const N: usize> From<[(&str, &str); N]> for Headers {
fn from(arr: [(&str, &str); N]) -> Self {
let mut headers = Headers::new();
for (k, v) in arr {
headers.insert(k, v);
}
headers
}
}
impl IntoIterator for Headers {
type Item = (String, String);
type IntoIter = std::collections::hash_map::IntoIter<String, String>;
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_headers_basic() {
let mut headers = Headers::new();
headers.insert("x-api-key", "test-key");
assert_eq!(headers.get("x-api-key"), Some(&"test-key".to_string()));
}
#[test]
fn test_headers_merge() {
let mut headers1 = Headers::new();
headers1.insert("key1", "value1");
let mut headers2 = Headers::new();
headers2.insert("key2", "value2");
headers1.merge(headers2);
assert_eq!(headers1.len(), 2);
}
#[test]
fn test_headers_from_tuple() {
let headers: Headers = ("x-api-key", "test").into();
assert_eq!(headers.get("x-api-key"), Some(&"test".to_string()));
}
#[test]
fn test_headers_from_array() {
let headers: Headers = [("key1", "val1"), ("key2", "val2")].into();
assert_eq!(headers.len(), 2);
}
}