autopush_common/
tags.rs

1// Pending actix4
2
3use std::collections::{BTreeMap, HashMap};
4
5use actix_web::{
6    dev::{Payload, RequestHead},
7    Error, FromRequest, HttpMessage, HttpRequest,
8};
9use futures::{future, future::Ready};
10use serde::{
11    ser::{SerializeMap, Serializer},
12    Serialize,
13};
14use serde_json::value::Value;
15
16#[derive(Clone, Debug, Default)]
17pub struct Tags {
18    pub tags: HashMap<String, String>,
19    pub extra: HashMap<String, String>,
20}
21
22impl Serialize for Tags {
23    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
24    where
25        S: Serializer,
26    {
27        let mut seq = serializer.serialize_map(Some(self.tags.len()))?;
28        for tag in self.tags.clone() {
29            if !tag.1.is_empty() {
30                seq.serialize_entry(&tag.0, &tag.1)?;
31            }
32        }
33        seq.end()
34    }
35}
36
37#[allow(dead_code)]
38fn insert_if_not_empty(label: &str, val: &str, tags: &mut HashMap<String, String>) {
39    if !val.is_empty() {
40        tags.insert(label.to_owned(), val.to_owned());
41    }
42}
43
44impl Tags {
45    #![allow(unused)] // TODO: Start using tags
46
47    pub fn from_request_head(req_head: &RequestHead) -> Tags {
48        req_head.into()
49    }
50
51    pub fn with_tags(tags: HashMap<String, String>) -> Tags {
52        if tags.is_empty() {
53            return Tags::default();
54        }
55        Tags {
56            tags,
57            extra: HashMap::new(),
58        }
59    }
60
61    pub fn get(&self, label: &str) -> String {
62        let none = "None".to_owned();
63        self.tags.get(label).map(String::from).unwrap_or(none)
64    }
65
66    pub fn extend(&mut self, tags: HashMap<String, String>) {
67        self.tags.extend(tags);
68    }
69
70    pub fn tag_tree(self) -> BTreeMap<String, String> {
71        let mut result = BTreeMap::new();
72
73        for (k, v) in self.tags {
74            result.insert(k.clone(), v.clone());
75        }
76        result
77    }
78
79    pub fn extra_tree(self) -> BTreeMap<String, Value> {
80        let mut result = BTreeMap::new();
81
82        for (k, v) in self.extra {
83            result.insert(k.clone(), Value::from(v));
84        }
85        result
86    }
87}
88
89impl slog::KV for Tags {
90    fn serialize(
91        &self,
92        _record: &slog::Record<'_>,
93        serializer: &mut dyn slog::Serializer,
94    ) -> slog::Result {
95        for (key, val) in &self.tags {
96            serializer.emit_str(slog::Key::from(key.clone()), val)?;
97        }
98        Ok(())
99    }
100}
101
102impl FromRequest for Tags {
103    type Error = Error;
104    type Future = Ready<Result<Self, Self::Error>>;
105
106    fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
107        let tags = {
108            let exts = req.extensions();
109            match exts.get::<Tags>() {
110                Some(t) => t.clone(),
111                None => Tags::from_request_head(req.head()),
112            }
113        };
114
115        future::ok(tags)
116    }
117}
118
119impl From<&RequestHead> for Tags {
120    fn from(req_head: &RequestHead) -> Self {
121        let mut tags = HashMap::new();
122        tags.insert("uri.method".to_owned(), req_head.method.to_string());
123        Tags {
124            tags,
125            extra: HashMap::new(),
126        }
127    }
128}
129
130impl From<Tags> for BTreeMap<String, String> {
131    fn from(tags: Tags) -> BTreeMap<String, String> {
132        let mut result = BTreeMap::new();
133
134        for (k, v) in tags.tags {
135            result.insert(k.clone(), v.clone());
136        }
137
138        result
139    }
140}